Browse Source

Merge pull request #116 from rust3ds/improve/api

Second wave of API changes
pull/126/head
Meziu 2 years ago committed by GitHub
parent
commit
ca8f13d28c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      ctru-rs/Cargo.toml
  2. 14
      ctru-rs/examples/audio-filters.rs
  3. 11
      ctru-rs/examples/buttons.rs
  4. 34
      ctru-rs/examples/camera-image.rs
  5. 16
      ctru-rs/examples/file-explorer.rs
  6. 10
      ctru-rs/examples/futures-basic.rs
  7. 10
      ctru-rs/examples/futures-tokio.rs
  8. 22
      ctru-rs/examples/gfx-3d-mode.rs
  9. 74
      ctru-rs/examples/gfx-bitmap.rs
  10. 12
      ctru-rs/examples/gfx-wide-mode.rs
  11. 14
      ctru-rs/examples/graphics-bitmap.rs
  12. 10
      ctru-rs/examples/hashmaps.rs
  13. 12
      ctru-rs/examples/hello-both-screens.rs
  14. 11
      ctru-rs/examples/hello-world.rs
  15. 11
      ctru-rs/examples/linear-memory.rs
  16. 13
      ctru-rs/examples/mii-selector.rs
  17. 10
      ctru-rs/examples/network-sockets.rs
  18. 11
      ctru-rs/examples/output-3dslink.rs
  19. 13
      ctru-rs/examples/romfs.rs
  20. 12
      ctru-rs/examples/software-keyboard.rs
  21. 13
      ctru-rs/examples/system-configuration.rs
  22. 10
      ctru-rs/examples/thread-basic.rs
  23. 10
      ctru-rs/examples/thread-info.rs
  24. 10
      ctru-rs/examples/thread-locals.rs
  25. 12
      ctru-rs/examples/time-rtc.rs
  26. 16
      ctru-rs/examples/title-info.rs
  27. 49
      ctru-rs/examples/touch-screen.rs
  28. 54
      ctru-rs/src/applets/mii_selector.rs
  29. 13
      ctru-rs/src/applets/swkbd.rs
  30. 6
      ctru-rs/src/console.rs
  31. 2
      ctru-rs/src/lib.rs
  32. 3
      ctru-rs/src/services/am.rs
  33. 2
      ctru-rs/src/services/apt.rs
  34. 27
      ctru-rs/src/services/cam.rs
  35. 32
      ctru-rs/src/services/cfgu.rs
  36. 33
      ctru-rs/src/services/fs.rs
  37. 173
      ctru-rs/src/services/gfx.rs
  38. 4
      ctru-rs/src/services/gspgpu.rs
  39. 75
      ctru-rs/src/services/hid.rs
  40. 12
      ctru-rs/src/services/ndsp/mod.rs
  41. 2
      ctru-rs/src/services/ndsp/wave.rs
  42. 4
      ctru-rs/src/services/ps.rs
  43. 4
      ctru-rs/src/services/romfs.rs
  44. 6
      ctru-rs/src/services/soc.rs
  45. 13
      ctru-rs/src/services/sslc.rs
  46. 10
      ctru-rs/src/test_runner.rs

2
ctru-rs/Cargo.toml

@ -1,5 +1,5 @@
[package] [package]
authors = [ "Rust3DS Org", "Ronald Kinard <furyhunter600@gmail.com>" ] authors = ["Rust3DS Org", "Ronald Kinard <furyhunter600@gmail.com>"]
description = "A safe wrapper around smealum's ctrulib." description = "A safe wrapper around smealum's ctrulib."
license = "Zlib" license = "Zlib"
name = "ctru-rs" name = "ctru-rs"

14
ctru-rs/examples/audio-filters.rs

@ -37,10 +37,10 @@ fn fill_buffer(audio_data: &mut [u8], frequency: f32) {
fn main() { fn main() {
ctru::use_panic_handler(); ctru::use_panic_handler();
let gfx = Gfx::init().expect("Couldn't obtain GFX controller"); let gfx = Gfx::new().expect("Couldn't obtain GFX controller");
let mut hid = Hid::init().expect("Couldn't obtain HID controller"); let mut hid = Hid::new().expect("Couldn't obtain HID controller");
let apt = Apt::init().expect("Couldn't obtain APT 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());
let mut note: usize = 4; 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_info1 = Wave::new(audio_data1, AudioFormat::PCM16Stereo, false);
let mut wave_info2 = Wave::new(audio_data2, 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` // This line isn't needed since the default NDSP configuration already sets the output mode to `Stereo`
ndsp.set_output_mode(OutputMode::Stereo); ndsp.set_output_mode(OutputMode::Stereo);
@ -154,10 +154,6 @@ fn main() {
altern = !altern; altern = !altern;
} }
// Flush and swap framebuffers
gfx.flush_buffers();
gfx.swap_buffers();
//Wait for VBlank //Wait for VBlank
gfx.wait_for_vblank(); gfx.wait_for_vblank();
} }

11
ctru-rs/examples/buttons.rs

@ -3,10 +3,10 @@ use ctru::prelude::*;
fn main() { fn main() {
ctru::use_panic_handler(); ctru::use_panic_handler();
let apt = Apt::init().unwrap(); let apt = Apt::new().unwrap();
let mut hid = Hid::init().unwrap(); let mut hid = Hid::new().unwrap();
let gfx = Gfx::init().unwrap(); let gfx = Gfx::new().unwrap();
let console = Console::init(gfx.top_screen.borrow_mut()); let console = Console::new(gfx.top_screen.borrow_mut());
println!("Hi there! Try pressing a button"); println!("Hi there! Try pressing a button");
println!("\x1b[29;16HPress Start to exit"); println!("\x1b[29;16HPress Start to exit");
@ -63,9 +63,6 @@ fn main() {
// Save our current key presses for the next frame // Save our current key presses for the next frame
old_keys = keys; old_keys = keys;
// Flush and swap framebuffers
gfx.flush_buffers();
gfx.swap_buffers();
gfx.wait_for_vblank(); gfx.wait_for_vblank();
} }
} }

34
ctru-rs/examples/camera-image.rs

@ -1,6 +1,6 @@
use ctru::prelude::*; use ctru::prelude::*;
use ctru::services::cam::{Cam, Camera, OutputFormat, ShutterSound, ViewSize}; 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 ctru::services::gspgpu::FramebufferFormat;
use std::time::Duration; use std::time::Duration;
@ -16,22 +16,21 @@ const WAIT_TIMEOUT: Duration = Duration::from_millis(300);
fn main() { fn main() {
ctru::use_panic_handler(); ctru::use_panic_handler();
let apt = Apt::init().expect("Failed to initialize Apt service."); let apt = Apt::new().expect("Failed to initialize Apt service.");
let mut hid = Hid::init().expect("Failed to initialize Hid service."); let mut hid = Hid::new().expect("Failed to initialize Hid service.");
let gfx = Gfx::init().expect("Failed to initialize GFX service."); let gfx = Gfx::new().expect("Failed to initialize GFX service.");
gfx.top_screen.borrow_mut().set_double_buffering(true); let mut top_screen = gfx.top_screen.borrow_mut();
gfx.top_screen top_screen.set_double_buffering(true);
.borrow_mut() top_screen.set_framebuffer_format(FramebufferFormat::Rgb565);
.set_framebuffer_format(FramebufferFormat::Rgb565);
gfx.bottom_screen.borrow_mut().set_double_buffering(false); let _console = Console::new(gfx.bottom_screen.borrow_mut());
let _console = Console::init(gfx.bottom_screen.borrow_mut());
let mut keys_down; let mut keys_down;
println!("Initializing camera"); 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; let camera = &mut cam.outer_right_cam;
@ -86,15 +85,12 @@ fn main() {
cam.play_shutter_sound(ShutterSound::Normal) cam.play_shutter_sound(ShutterSound::Normal)
.expect("Failed to play shutter sound"); .expect("Failed to play shutter sound");
rotate_image_to_screen( rotate_image_to_screen(&buf, top_screen.raw_framebuffer().ptr, WIDTH, HEIGHT);
&buf,
gfx.top_screen.borrow_mut().raw_framebuffer().ptr, // We will only flush the "camera" screen, since the other screen is handled by `Console`
WIDTH, top_screen.flush_buffers();
HEIGHT, top_screen.swap_buffers();
);
gfx.flush_buffers();
gfx.swap_buffers();
gfx.wait_for_vblank(); gfx.wait_for_vblank();
} }
} }

16
ctru-rs/examples/file-explorer.rs

@ -11,14 +11,14 @@ use std::path::{Path, PathBuf};
fn main() { fn main() {
ctru::use_panic_handler(); ctru::use_panic_handler();
let apt = Apt::init().unwrap(); let apt = Apt::new().unwrap();
let mut hid = Hid::init().unwrap(); let mut hid = Hid::new().unwrap();
let gfx = Gfx::init().unwrap(); let gfx = Gfx::new().unwrap();
#[cfg(all(feature = "romfs", romfs_exists))] #[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> { struct FileExplorer<'a> {
@ -32,10 +32,10 @@ struct FileExplorer<'a> {
} }
impl<'a> 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(); let mut top_screen = gfx.top_screen.borrow_mut();
top_screen.set_wide_mode(true); top_screen.set_wide_mode(true);
let console = Console::init(top_screen); let console = Console::new(top_screen);
FileExplorer { FileExplorer {
apt, apt,
@ -68,8 +68,6 @@ impl<'a> FileExplorer<'a> {
self.get_input_and_run(Self::set_exact_path); self.get_input_and_run(Self::set_exact_path);
} }
self.gfx.flush_buffers();
self.gfx.swap_buffers();
self.gfx.wait_for_vblank(); self.gfx.wait_for_vblank();
} }
} }

10
ctru-rs/examples/futures-basic.rs

@ -15,10 +15,10 @@ use std::os::horizon::thread::BuilderExt;
fn main() { fn main() {
ctru::use_panic_handler(); ctru::use_panic_handler();
let gfx = Gfx::init().expect("Couldn't obtain GFX controller"); let gfx = Gfx::new().expect("Couldn't obtain GFX controller");
let mut hid = Hid::init().expect("Couldn't obtain HID controller"); let mut hid = Hid::new().expect("Couldn't obtain HID controller");
let apt = Apt::init().expect("Couldn't obtain APT 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());
// Give ourselves up to 30% of the system core's time // Give ourselves up to 30% of the system core's time
apt.set_app_cpu_time_limit(30) apt.set_app_cpu_time_limit(30)
@ -68,8 +68,6 @@ fn main() {
frame_count = 0; frame_count = 0;
} }
gfx.flush_buffers();
gfx.swap_buffers();
gfx.wait_for_vblank(); gfx.wait_for_vblank();
} }
} }

10
ctru-rs/examples/futures-tokio.rs

@ -8,10 +8,10 @@ use std::time::Duration;
fn main() { fn main() {
ctru::use_panic_handler(); ctru::use_panic_handler();
let gfx = Gfx::init().expect("Couldn't obtain GFX controller"); let gfx = Gfx::new().expect("Couldn't obtain GFX controller");
let mut hid = Hid::init().expect("Couldn't obtain HID controller"); let mut hid = Hid::new().expect("Couldn't obtain HID controller");
let apt = Apt::init().expect("Couldn't obtain APT 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());
// Give ourselves up to 30% of the system core's time // Give ourselves up to 30% of the system core's time
apt.set_app_cpu_time_limit(30) apt.set_app_cpu_time_limit(30)
@ -63,8 +63,6 @@ fn main() {
break; break;
} }
gfx.flush_buffers();
gfx.swap_buffers();
gfx.wait_for_vblank(); gfx.wait_for_vblank();
} }
} }

22
ctru-rs/examples/gfx-3d-mode.rs

@ -1,5 +1,5 @@
use ctru::prelude::*; 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. /// See `graphics-bitmap.rs` for details on how the image is generated.
/// ///
@ -12,17 +12,16 @@ static ZERO: &[u8] = &[0; IMAGE.len()];
fn main() { fn main() {
ctru::use_panic_handler(); ctru::use_panic_handler();
let gfx = Gfx::init().expect("Couldn't obtain GFX controller"); let gfx = Gfx::new().expect("Couldn't obtain GFX controller");
let mut hid = Hid::init().expect("Couldn't obtain HID controller"); let mut hid = Hid::new().expect("Couldn't obtain HID controller");
let apt = Apt::init().expect("Couldn't obtain APT controller"); let apt = Apt::new().expect("Couldn't obtain APT controller");
let _console = Console::init(gfx.bottom_screen.borrow_mut()); 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)."); 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); gfx.top_screen.borrow_mut().set_double_buffering(true);
let top_screen = TopScreen3D::from(&gfx.top_screen); let mut top_screen = TopScreen3D::from(&gfx.top_screen);
let (mut left, mut right) = top_screen.split_mut();
let mut current_side = Side::Left; let mut current_side = Side::Left;
@ -35,6 +34,8 @@ fn main() {
break; break;
} }
let (mut left, mut right) = top_screen.split_mut();
let left_buf = left.raw_framebuffer(); let left_buf = left.raw_framebuffer();
let right_buf = right.raw_framebuffer(); let right_buf = right.raw_framebuffer();
@ -61,9 +62,10 @@ fn main() {
buf.copy_from(IMAGE.as_ptr(), IMAGE.len()); buf.copy_from(IMAGE.as_ptr(), IMAGE.len());
} }
// Flush and swap framebuffers drop((left, right));
gfx.flush_buffers();
gfx.swap_buffers(); top_screen.flush_buffers();
top_screen.swap_buffers();
//Wait for VBlank //Wait for VBlank
gfx.wait_for_vblank(); gfx.wait_for_vblank();

74
ctru-rs/examples/gfx-bitmap.rs

@ -0,0 +1,74 @@
use ctru::prelude::*;
use ctru::services::gfx::{Flush, Screen, Swap};
/// Ferris image taken from <https://rustacean.net> 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();
}
}

12
ctru-rs/examples/gfx-wide-mode.rs

@ -3,10 +3,10 @@ use ctru::prelude::*;
fn main() { fn main() {
ctru::use_panic_handler(); ctru::use_panic_handler();
let apt = Apt::init().unwrap(); let apt = Apt::new().unwrap();
let mut hid = Hid::init().unwrap(); let mut hid = Hid::new().unwrap();
let gfx = Gfx::init().unwrap(); let gfx = Gfx::new().unwrap();
let mut console = Console::init(gfx.top_screen.borrow_mut()); let mut console = Console::new(gfx.top_screen.borrow_mut());
println!("Press A to enable/disable wide screen mode."); println!("Press A to enable/disable wide screen mode.");
@ -23,12 +23,10 @@ fn main() {
let wide_mode = gfx.top_screen.borrow().is_wide(); let wide_mode = gfx.top_screen.borrow().is_wide();
gfx.top_screen.borrow_mut().set_wide_mode(!wide_mode); 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."); println!("Press A to enable/disable wide screen mode.");
} }
gfx.flush_buffers();
gfx.swap_buffers();
gfx.wait_for_vblank(); gfx.wait_for_vblank();
} }
} }

14
ctru-rs/examples/graphics-bitmap.rs

@ -1,5 +1,5 @@
use ctru::prelude::*; use ctru::prelude::*;
use ctru::services::gfx::Screen; use ctru::services::gfx::{Flush, Screen, Swap};
/// Ferris image taken from <https://rustacean.net> and scaled down to 320x240px. /// Ferris image taken from <https://rustacean.net> and scaled down to 320x240px.
/// To regenerate the data, you will need to install `imagemagick` and run this /// 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() { fn main() {
ctru::use_panic_handler(); ctru::use_panic_handler();
let gfx = Gfx::init().expect("Couldn't obtain GFX controller"); let gfx = Gfx::new().expect("Couldn't obtain GFX controller");
let mut hid = Hid::init().expect("Couldn't obtain HID controller"); let mut hid = Hid::new().expect("Couldn't obtain HID controller");
let apt = Apt::init().expect("Couldn't obtain APT 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());
println!("\x1b[21;16HPress Start to exit."); println!("\x1b[21;16HPress Start to exit.");
@ -48,8 +48,8 @@ fn main() {
} }
// Flush and swap framebuffers // Flush and swap framebuffers
gfx.flush_buffers(); bottom_screen.flush_buffers();
gfx.swap_buffers(); bottom_screen.swap_buffers();
//Wait for VBlank //Wait for VBlank
gfx.wait_for_vblank(); gfx.wait_for_vblank();

10
ctru-rs/examples/hashmaps.rs

@ -8,10 +8,10 @@ fn main() {
// HashMaps generate hashes thanks to the 3DS' cryptografically secure generator. // HashMaps generate hashes thanks to the 3DS' cryptografically secure generator.
// This generator is only active when activating the `PS` service. // This generator is only active when activating the `PS` service.
// This service is automatically initialized. // This service is automatically initialized.
let apt = Apt::init().unwrap(); let apt = Apt::new().unwrap();
let mut hid = Hid::init().unwrap(); let mut hid = Hid::new().unwrap();
let gfx = Gfx::init().unwrap(); let gfx = Gfx::new().unwrap();
let _console = Console::init(gfx.top_screen.borrow_mut()); let _console = Console::new(gfx.top_screen.borrow_mut());
let mut map = std::collections::HashMap::new(); let mut map = std::collections::HashMap::new();
map.insert("A Key!", 102); map.insert("A Key!", 102);
@ -21,8 +21,6 @@ fn main() {
println!("{map:#?}"); println!("{map:#?}");
while apt.main_loop() { while apt.main_loop() {
gfx.flush_buffers();
gfx.swap_buffers();
gfx.wait_for_vblank(); gfx.wait_for_vblank();
hid.scan_input(); hid.scan_input();

12
ctru-rs/examples/hello-both-screens.rs

@ -3,16 +3,16 @@ use ctru::prelude::*;
fn main() { fn main() {
ctru::use_panic_handler(); ctru::use_panic_handler();
let apt = Apt::init().unwrap(); let apt = Apt::new().unwrap();
let mut hid = Hid::init().unwrap(); let mut hid = Hid::new().unwrap();
let gfx = Gfx::init().unwrap(); let gfx = Gfx::new().unwrap();
// Start a console on the top screen // 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. // Start a console on the bottom screen.
// The most recently initialized console will be active by default // 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 // Let's print on the top screen first
top_screen.select(); top_screen.select();
@ -27,8 +27,6 @@ fn main() {
println!("\x1b[29;16HPress Start to exit"); println!("\x1b[29;16HPress Start to exit");
while apt.main_loop() { while apt.main_loop() {
gfx.flush_buffers();
gfx.swap_buffers();
gfx.wait_for_vblank(); gfx.wait_for_vblank();
hid.scan_input(); hid.scan_input();

11
ctru-rs/examples/hello-world.rs

@ -5,10 +5,10 @@ use std::io::BufWriter;
fn main() { fn main() {
ctru::use_panic_handler(); ctru::use_panic_handler();
let gfx = Gfx::init().expect("Couldn't obtain GFX controller"); let gfx = Gfx::new().expect("Couldn't obtain GFX controller");
let mut hid = Hid::init().expect("Couldn't obtain HID controller"); let mut hid = Hid::new().expect("Couldn't obtain HID controller");
let apt = Apt::init().expect("Couldn't obtain APT 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());
let out = b"Hello fellow Rustaceans, I'm on the Nintendo 3DS!"; let out = b"Hello fellow Rustaceans, I'm on the Nintendo 3DS!";
let width = 24; let width = 24;
@ -29,9 +29,6 @@ fn main() {
if hid.keys_down().contains(KeyPad::START) { if hid.keys_down().contains(KeyPad::START) {
break; break;
} }
// Flush and swap framebuffers
gfx.flush_buffers();
gfx.swap_buffers();
//Wait for VBlank //Wait for VBlank
gfx.wait_for_vblank(); gfx.wait_for_vblank();

11
ctru-rs/examples/linear-memory.rs

@ -6,10 +6,10 @@ use ctru::prelude::*;
fn main() { fn main() {
ctru::use_panic_handler(); ctru::use_panic_handler();
let gfx = Gfx::init().expect("Couldn't obtain GFX controller"); let gfx = Gfx::new().expect("Couldn't obtain GFX controller");
let mut hid = Hid::init().expect("Couldn't obtain HID controller"); let mut hid = Hid::new().expect("Couldn't obtain HID controller");
let apt = Apt::init().expect("Couldn't obtain APT 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());
let linear_space_before = LinearAllocator::free_space(); let linear_space_before = LinearAllocator::free_space();
@ -37,9 +37,6 @@ fn main() {
if hid.keys_down().contains(KeyPad::START) { if hid.keys_down().contains(KeyPad::START) {
break; break;
} }
// Flush and swap framebuffers
gfx.flush_buffers();
gfx.swap_buffers();
//Wait for VBlank //Wait for VBlank
gfx.wait_for_vblank(); gfx.wait_for_vblank();

13
ctru-rs/examples/mii-selector.rs

@ -4,12 +4,12 @@ use ctru::prelude::*;
fn main() { fn main() {
ctru::use_panic_handler(); ctru::use_panic_handler();
let gfx = Gfx::init().expect("Couldn't obtain GFX controller"); let gfx = Gfx::new().expect("Couldn't obtain GFX controller");
let mut hid = Hid::init().expect("Couldn't obtain HID controller"); let mut hid = Hid::new().expect("Couldn't obtain HID controller");
let apt = Apt::init().expect("Couldn't obtain APT 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());
let mut mii_selector = MiiSelector::init(); let mut mii_selector = MiiSelector::new();
mii_selector.set_initial_index(3); mii_selector.set_initial_index(3);
mii_selector.blacklist_user_mii(0.into()); mii_selector.blacklist_user_mii(0.into());
mii_selector.set_title("Great Mii Selector!"); mii_selector.set_title("Great Mii Selector!");
@ -33,9 +33,6 @@ fn main() {
if hid.keys_down().contains(KeyPad::START) { if hid.keys_down().contains(KeyPad::START) {
break; break;
} }
// Flush and swap framebuffers
gfx.flush_buffers();
gfx.swap_buffers();
//Wait for VBlank //Wait for VBlank
gfx.wait_for_vblank(); gfx.wait_for_vblank();

10
ctru-rs/examples/network-sockets.rs

@ -7,14 +7,14 @@ use std::time::Duration;
fn main() { fn main() {
ctru::use_panic_handler(); ctru::use_panic_handler();
let gfx = Gfx::init().unwrap(); let gfx = Gfx::new().unwrap();
let _console = Console::init(gfx.top_screen.borrow_mut()); let _console = Console::new(gfx.top_screen.borrow_mut());
let mut hid = Hid::init().unwrap(); let mut hid = Hid::new().unwrap();
let apt = Apt::init().unwrap(); let apt = Apt::new().unwrap();
println!("\nlibctru sockets demo\n"); 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(); let server = TcpListener::bind("0.0.0.0:80").unwrap();
server.set_nonblocking(true).unwrap(); server.set_nonblocking(true).unwrap();

11
ctru-rs/examples/output-3dslink.rs

@ -13,11 +13,11 @@ use ctru::prelude::*;
fn main() { fn main() {
ctru::use_panic_handler(); ctru::use_panic_handler();
let gfx = Gfx::init().expect("Couldn't obtain GFX controller"); let gfx = Gfx::new().expect("Couldn't obtain GFX controller");
let mut hid = Hid::init().expect("Couldn't obtain HID controller"); let mut hid = Hid::new().expect("Couldn't obtain HID controller");
let apt = Apt::init().expect("Couldn't obtain APT 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) soc.redirect_to_3dslink(true, true)
.expect("unable to redirect stdout/err to 3dslink server"); .expect("unable to redirect stdout/err to 3dslink server");
@ -33,9 +33,6 @@ fn main() {
if hid.keys_down().contains(KeyPad::START) { if hid.keys_down().contains(KeyPad::START) {
break; break;
} }
// Flush and swap framebuffers
gfx.flush_buffers();
gfx.swap_buffers();
//Wait for VBlank //Wait for VBlank
gfx.wait_for_vblank(); gfx.wait_for_vblank();

13
ctru-rs/examples/romfs.rs

@ -3,17 +3,17 @@ use ctru::prelude::*;
fn main() { fn main() {
ctru::use_panic_handler(); ctru::use_panic_handler();
let gfx = Gfx::init().expect("Couldn't obtain GFX controller"); let gfx = Gfx::new().expect("Couldn't obtain GFX controller");
let mut hid = Hid::init().expect("Couldn't obtain HID controller"); let mut hid = Hid::new().expect("Couldn't obtain HID controller");
let apt = Apt::init().expect("Couldn't obtain APT 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());
cfg_if::cfg_if! { cfg_if::cfg_if! {
// Run this code if RomFS are wanted and available // Run this code if RomFS are wanted and available
// This never fails as `ctru-rs` examples inherit all of the `ctru` features, // 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 // but it might if a normal user application wasn't setup correctly
if #[cfg(all(feature = "romfs", romfs_exists))] { 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(); let f = std::fs::read_to_string("romfs:/test-file.txt").unwrap();
println!("Contents of test-file.txt: \n{f}\n"); println!("Contents of test-file.txt: \n{f}\n");
@ -36,9 +36,6 @@ fn main() {
if hid.keys_down().contains(KeyPad::START) { if hid.keys_down().contains(KeyPad::START) {
break; break;
} }
// Flush and swap framebuffers
gfx.flush_buffers();
gfx.swap_buffers();
//Wait for VBlank //Wait for VBlank
gfx.wait_for_vblank(); gfx.wait_for_vblank();

12
ctru-rs/examples/software-keyboard.rs

@ -4,23 +4,21 @@ use ctru::prelude::*;
fn main() { fn main() {
ctru::use_panic_handler(); ctru::use_panic_handler();
let apt = Apt::init().unwrap(); let apt = Apt::new().unwrap();
let mut hid = Hid::init().unwrap(); let mut hid = Hid::new().unwrap();
let gfx = Gfx::init().unwrap(); let gfx = Gfx::new().unwrap();
let _console = Console::init(gfx.top_screen.borrow_mut()); let _console = Console::new(gfx.top_screen.borrow_mut());
println!("Press A to enter some text or press Start to quit"); println!("Press A to enter some text or press Start to quit");
while apt.main_loop() { while apt.main_loop() {
gfx.flush_buffers();
gfx.swap_buffers();
gfx.wait_for_vblank(); gfx.wait_for_vblank();
hid.scan_input(); hid.scan_input();
if hid.keys_down().contains(KeyPad::A) { if hid.keys_down().contains(KeyPad::A) {
// Prepares a software keyboard with two buttons: One to cancel input and one // 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. // configurations.
let mut keyboard = Swkbd::default(); let mut keyboard = Swkbd::default();

13
ctru-rs/examples/system-configuration.rs

@ -4,11 +4,11 @@ use ctru::services::cfgu::Cfgu;
fn main() { fn main() {
ctru::use_panic_handler(); ctru::use_panic_handler();
let gfx = Gfx::init().expect("Couldn't obtain GFX controller"); let gfx = Gfx::new().expect("Couldn't obtain GFX controller");
let mut hid = Hid::init().expect("Couldn't obtain HID controller"); let mut hid = Hid::new().expect("Couldn't obtain HID controller");
let apt = Apt::init().expect("Couldn't obtain APT controller"); let apt = Apt::new().expect("Couldn't obtain APT controller");
let cfgu = Cfgu::init().expect("Couldn't obtain CFGU controller"); let cfgu = Cfgu::new().expect("Couldn't obtain CFGU controller");
let _console = Console::init(gfx.top_screen.borrow_mut()); let _console = Console::new(gfx.top_screen.borrow_mut());
println!("\x1b[0;0HRegion: {:?}", cfgu.region().unwrap()); println!("\x1b[0;0HRegion: {:?}", cfgu.region().unwrap());
println!("\x1b[10;0HLanguage: {:?}", cfgu.language().unwrap()); println!("\x1b[10;0HLanguage: {:?}", cfgu.language().unwrap());
@ -22,9 +22,6 @@ fn main() {
if hid.keys_down().contains(KeyPad::START) { if hid.keys_down().contains(KeyPad::START) {
break; break;
} }
// Flush and swap framebuffers
gfx.flush_buffers();
gfx.swap_buffers();
//Wait for VBlank //Wait for VBlank
gfx.wait_for_vblank(); gfx.wait_for_vblank();

10
ctru-rs/examples/thread-basic.rs

@ -8,10 +8,10 @@ use std::time::Duration;
fn main() { fn main() {
ctru::use_panic_handler(); ctru::use_panic_handler();
let apt = Apt::init().unwrap(); let apt = Apt::new().unwrap();
let mut hid = Hid::init().unwrap(); let mut hid = Hid::new().unwrap();
let gfx = Gfx::init().unwrap(); let gfx = Gfx::new().unwrap();
let _console = Console::init(gfx.top_screen.borrow_mut()); let _console = Console::new(gfx.top_screen.borrow_mut());
let prio = std::os::horizon::thread::current_priority(); let prio = std::os::horizon::thread::current_priority();
println!("Main thread prio: {}\n", prio); println!("Main thread prio: {}\n", prio);
@ -34,8 +34,6 @@ fn main() {
} }
while apt.main_loop() { while apt.main_loop() {
gfx.flush_buffers();
gfx.swap_buffers();
gfx.wait_for_vblank(); gfx.wait_for_vblank();
hid.scan_input(); hid.scan_input();

10
ctru-rs/examples/thread-info.rs

@ -9,10 +9,10 @@ use std::os::horizon::thread::BuilderExt;
fn main() { fn main() {
ctru::use_panic_handler(); ctru::use_panic_handler();
let gfx = Gfx::init().expect("Couldn't obtain GFX controller"); let gfx = Gfx::new().expect("Couldn't obtain GFX controller");
let mut hid = Hid::init().expect("Couldn't obtain HID controller"); let mut hid = Hid::new().expect("Couldn't obtain HID controller");
let apt = Apt::init().expect("Couldn't obtain APT 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());
// Give ourselves up to 30% of the system core's time // Give ourselves up to 30% of the system core's time
apt.set_app_cpu_time_limit(30) apt.set_app_cpu_time_limit(30)
@ -45,8 +45,6 @@ fn main() {
break; break;
} }
gfx.flush_buffers();
gfx.swap_buffers();
gfx.wait_for_vblank(); gfx.wait_for_vblank();
} }
} }

10
ctru-rs/examples/thread-locals.rs

@ -12,11 +12,11 @@ std::thread_local! {
fn main() { fn main() {
ctru::use_panic_handler(); 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); gfx.top_screen.borrow_mut().set_wide_mode(true);
let mut hid = Hid::init().expect("Couldn't obtain HID controller"); let mut hid = Hid::new().expect("Couldn't obtain HID controller");
let apt = Apt::init().expect("Couldn't obtain APT 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());
// Give ourselves up to 30% of the system core's time // Give ourselves up to 30% of the system core's time
apt.set_app_cpu_time_limit(30) apt.set_app_cpu_time_limit(30)
@ -61,8 +61,6 @@ fn main() {
break; break;
} }
gfx.flush_buffers();
gfx.swap_buffers();
gfx.wait_for_vblank(); gfx.wait_for_vblank();
} }
} }

12
ctru-rs/examples/time-rtc.rs

@ -3,11 +3,11 @@ use ctru::prelude::*;
fn main() { fn main() {
ctru::use_panic_handler(); ctru::use_panic_handler();
let gfx = Gfx::init().expect("Couldn't obtain GFX controller"); let gfx = Gfx::new().expect("Couldn't obtain GFX controller");
let mut hid = Hid::init().expect("Couldn't obtain HID controller"); let mut hid = Hid::new().expect("Couldn't obtain HID controller");
let apt = Apt::init().expect("Couldn't obtain APT 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."); 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!("\x1b[1;1H{hours:0>2}:{minutes:0>2}:{seconds:0>2}");
println!("{weekday} {month} {day} {year}"); println!("{weekday} {month} {day} {year}");
// Flush and swap framebuffers
gfx.flush_buffers();
gfx.swap_buffers();
//Wait for VBlank //Wait for VBlank
gfx.wait_for_vblank(); gfx.wait_for_vblank();
} }

16
ctru-rs/examples/title-info.rs

@ -5,12 +5,12 @@ use ctru::services::fs::FsMediaType;
fn main() { fn main() {
ctru::use_panic_handler(); ctru::use_panic_handler();
let gfx = Gfx::init().expect("Couldn't obtain GFX controller"); let gfx = Gfx::new().expect("Couldn't obtain GFX controller");
let mut hid = Hid::init().expect("Couldn't obtain HID controller"); let mut hid = Hid::new().expect("Couldn't obtain HID controller");
let apt = Apt::init().expect("Couldn't obtain APT controller"); let apt = Apt::new().expect("Couldn't obtain APT controller");
let am = Am::init().expect("Couldn't obtain AM controller"); let am = Am::new().expect("Couldn't obtain AM controller");
let top_screen = Console::init(gfx.top_screen.borrow_mut()); let top_screen = Console::new(gfx.top_screen.borrow_mut());
let bottom_screen = Console::init(gfx.bottom_screen.borrow_mut()); let bottom_screen = Console::new(gfx.bottom_screen.borrow_mut());
let sd_count = am let sd_count = am
.title_count(FsMediaType::Sd) .title_count(FsMediaType::Sd)
@ -106,10 +106,6 @@ fn main() {
refresh = false; refresh = false;
} }
// Flush and swap framebuffers
gfx.flush_buffers();
gfx.swap_buffers();
//Wait for VBlank //Wait for VBlank
gfx.wait_for_vblank(); gfx.wait_for_vblank();
} }

49
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();
}
}

54
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 /// Index of a Mii used to configure some parameters of the Mii Selector
/// Can be either a single index, or _all_ Miis /// Can be either a single index, or _all_ Miis
#[derive(Debug, Clone)] #[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub enum MiiConfigIndex { pub enum Index {
Index(u32), Index(u32),
All, All,
} }
/// The type of a Mii with their respective data /// The type of a Mii with their respective data
#[derive(Debug, Clone)] #[derive(Debug, Clone, Eq, PartialEq)]
pub enum MiiType { pub enum MiiType {
Guest { index: u32, name: String }, Guest { index: u32, name: String },
User, User,
@ -41,7 +41,7 @@ bitflags! {
/// ``` /// ```
/// use ctru::applets::mii_selector::MiiSelector; /// 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"); /// mii_selector.set_title("Example Mii selector");
/// ///
/// let result = mii_selector.launch().unwrap(); /// let result = mii_selector.launch().unwrap();
@ -54,7 +54,7 @@ pub struct MiiSelector {
/// Return value from a MiiSelector's launch /// Return value from a MiiSelector's launch
#[non_exhaustive] #[non_exhaustive]
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct MiiSelectorReturn { pub struct SelectionResult {
pub mii_data: MiiData, pub mii_data: MiiData,
pub is_mii_selected: bool, pub is_mii_selected: bool,
pub mii_type: MiiType, pub mii_type: MiiType,
@ -62,13 +62,13 @@ pub struct MiiSelectorReturn {
/// Error type for the Mii selector /// Error type for the Mii selector
#[derive(Copy, Clone, Debug, Eq, PartialEq)] #[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum MiiLaunchError { pub enum LaunchError {
InvalidChecksum, InvalidChecksum,
} }
impl MiiSelector { impl MiiSelector {
/// Initializes a Mii Selector /// Initializes a Mii Selector
pub fn init() -> Self { pub fn new() -> Self {
let mut config = Box::<ctru_sys::MiiSelectorConf>::default(); let mut config = Box::<ctru_sys::MiiSelectorConf>::default();
unsafe { unsafe {
ctru_sys::miiSelectorInit(config.as_mut()); ctru_sys::miiSelectorInit(config.as_mut());
@ -94,40 +94,40 @@ impl MiiSelector {
} }
/// Whitelist a guest Mii /// 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 { let index = match mii_index {
MiiConfigIndex::Index(i) => i, Index::Index(i) => i,
MiiConfigIndex::All => ctru_sys::MIISELECTOR_GUESTMII_SLOTS, Index::All => ctru_sys::MIISELECTOR_GUESTMII_SLOTS,
}; };
unsafe { ctru_sys::miiSelectorWhitelistGuestMii(self.config.as_mut(), index) } unsafe { ctru_sys::miiSelectorWhitelistGuestMii(self.config.as_mut(), index) }
} }
/// Blacklist a guest Mii /// 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 { let index = match mii_index {
MiiConfigIndex::Index(i) => i, Index::Index(i) => i,
MiiConfigIndex::All => ctru_sys::MIISELECTOR_GUESTMII_SLOTS, Index::All => ctru_sys::MIISELECTOR_GUESTMII_SLOTS,
}; };
unsafe { ctru_sys::miiSelectorBlacklistGuestMii(self.config.as_mut(), index) } unsafe { ctru_sys::miiSelectorBlacklistGuestMii(self.config.as_mut(), index) }
} }
/// Whitelist a user Mii /// 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 { let index = match mii_index {
MiiConfigIndex::Index(i) => i, Index::Index(i) => i,
MiiConfigIndex::All => ctru_sys::MIISELECTOR_USERMII_SLOTS, Index::All => ctru_sys::MIISELECTOR_USERMII_SLOTS,
}; };
unsafe { ctru_sys::miiSelectorWhitelistUserMii(self.config.as_mut(), index) } unsafe { ctru_sys::miiSelectorWhitelistUserMii(self.config.as_mut(), index) }
} }
/// Blacklist a user Mii /// 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 { let index = match mii_index {
MiiConfigIndex::Index(i) => i, Index::Index(i) => i,
MiiConfigIndex::All => ctru_sys::MIISELECTOR_USERMII_SLOTS, Index::All => ctru_sys::MIISELECTOR_USERMII_SLOTS,
}; };
unsafe { ctru_sys::miiSelectorBlacklistUserMii(self.config.as_mut(), index) } unsafe { ctru_sys::miiSelectorBlacklistUserMii(self.config.as_mut(), index) }
@ -143,24 +143,30 @@ impl MiiSelector {
/// Launch the Mii Selector. /// Launch the Mii Selector.
/// Returns an error when the checksum of the Mii is invalid. /// Returns an error when the checksum of the Mii is invalid.
pub fn launch(&mut self) -> Result<MiiSelectorReturn, MiiLaunchError> { pub fn launch(&mut self) -> Result<SelectionResult, LaunchError> {
let mut return_val = Box::<ctru_sys::MiiSelectorReturn>::default(); let mut return_val = Box::<ctru_sys::MiiSelectorReturn>::default();
unsafe { ctru_sys::miiSelectorLaunch(self.config.as_mut(), return_val.as_mut()) } unsafe { ctru_sys::miiSelectorLaunch(self.config.as_mut(), return_val.as_mut()) }
if unsafe { ctru_sys::miiSelectorChecksumIsValid(return_val.as_mut()) } { if unsafe { ctru_sys::miiSelectorChecksumIsValid(return_val.as_mut()) } {
Ok((*return_val).into()) Ok((*return_val).into())
} else { } else {
Err(MiiLaunchError::InvalidChecksum) Err(LaunchError::InvalidChecksum)
} }
} }
} }
impl From<ctru_sys::MiiSelectorReturn> for MiiSelectorReturn { impl Default for MiiSelector {
fn default() -> Self {
Self::new()
}
}
impl From<ctru_sys::MiiSelectorReturn> for SelectionResult {
fn from(ret: ctru_sys::MiiSelectorReturn) -> Self { fn from(ret: ctru_sys::MiiSelectorReturn) -> Self {
let raw_mii_data = ret.mii; let raw_mii_data = ret.mii;
let mut guest_mii_name = ret.guest_mii_name; let mut guest_mii_name = ret.guest_mii_name;
MiiSelectorReturn { SelectionResult {
mii_data: raw_mii_data.into(), mii_data: raw_mii_data.into(),
is_mii_selected: ret.no_mii_selected == 0, is_mii_selected: ret.no_mii_selected == 0,
mii_type: if ret.guest_mii_index != 0xFFFFFFFF { mii_type: if ret.guest_mii_index != 0xFFFFFFFF {
@ -179,7 +185,7 @@ impl From<ctru_sys::MiiSelectorReturn> for MiiSelectorReturn {
} }
} }
impl From<u32> for MiiConfigIndex { impl From<u32> for Index {
fn from(v: u32) -> Self { fn from(v: u32) -> Self {
Self::Index(v) Self::Index(v)
} }

13
ctru-rs/src/applets/swkbd.rs

@ -7,6 +7,7 @@ use std::iter::once;
use std::str; use std::str;
/// An instance of the software keyboard. /// An instance of the software keyboard.
#[derive(Clone)]
pub struct Swkbd { pub struct Swkbd {
state: Box<SwkbdState>, state: Box<SwkbdState>,
} }
@ -18,7 +19,7 @@ pub struct Swkbd {
/// Numpad is a number pad. /// Numpad is a number pad.
/// Western is a text keyboard without japanese symbols (only applies to JPN systems). For other /// Western is a text keyboard without japanese symbols (only applies to JPN systems). For other
/// systems it's the same as a Normal keyboard. /// systems it's the same as a Normal keyboard.
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[repr(u32)] #[repr(u32)]
pub enum Kind { pub enum Kind {
Normal = ctru_sys::SWKBD_TYPE_NORMAL, Normal = ctru_sys::SWKBD_TYPE_NORMAL,
@ -28,7 +29,7 @@ pub enum Kind {
} }
/// Represents which button the user pressed to close the software keyboard. /// Represents which button the user pressed to close the software keyboard.
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[repr(u32)] #[repr(u32)]
pub enum Button { pub enum Button {
Left = ctru_sys::SWKBD_BUTTON_LEFT, Left = ctru_sys::SWKBD_BUTTON_LEFT,
@ -37,7 +38,7 @@ pub enum Button {
} }
/// Error type for the software keyboard. /// Error type for the software keyboard.
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[repr(i32)] #[repr(i32)]
pub enum Error { pub enum Error {
InvalidInput = ctru_sys::SWKBD_INVALID_INPUT, InvalidInput = ctru_sys::SWKBD_INVALID_INPUT,
@ -51,7 +52,7 @@ pub enum Error {
} }
/// Restrictions on keyboard input /// Restrictions on keyboard input
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[repr(u32)] #[repr(u32)]
pub enum ValidInput { pub enum ValidInput {
Anything = ctru_sys::SWKBD_ANYTHING, Anything = ctru_sys::SWKBD_ANYTHING,
@ -89,7 +90,7 @@ bitflags! {
impl Swkbd { impl Swkbd {
/// Initializes a software keyboard of the specified type and the chosen number of buttons /// Initializes a software keyboard of the specified type and the chosen number of buttons
/// (from 1-3). /// (from 1-3).
pub fn init(keyboard_type: Kind, num_buttons: i32) -> Self { pub fn new(keyboard_type: Kind, num_buttons: i32) -> Self {
unsafe { unsafe {
let mut state = Box::<SwkbdState>::default(); let mut state = Box::<SwkbdState>::default();
swkbdInit(state.as_mut(), keyboard_type.into(), num_buttons, -1); swkbdInit(state.as_mut(), keyboard_type.into(), num_buttons, -1);
@ -207,7 +208,7 @@ impl Swkbd {
impl Default for Swkbd { impl Default for Swkbd {
fn default() -> Self { fn default() -> Self {
Swkbd::init(Kind::Normal, 2) Swkbd::new(Kind::Normal, 2)
} }
} }

6
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 /// Initialize a console on the chosen screen, overwriting whatever was on the screen
/// previously (including other consoles). The new console is automatically selected for /// previously (including other consoles). The new console is automatically selected for
/// printing. /// 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::<PrintConsole>::default(); let mut context = Box::<PrintConsole>::default();
unsafe { consoleInit(screen.as_raw(), context.as_mut()) }; unsafe { consoleInit(screen.as_raw(), context.as_mut()) };

2
ctru-rs/src/lib.rs

@ -54,7 +54,7 @@ fn panic_hook_setup() {
if main_thread == std::thread::current().id() && console::Console::exists() { if main_thread == std::thread::current().id() && console::Console::exists() {
println!("\nPress SELECT to exit the software"); println!("\nPress SELECT to exit the software");
match Hid::init() { match Hid::new() {
Ok(mut hid) => loop { Ok(mut hid) => loop {
hid.scan_input(); hid.scan_input();
let keys = hid.keys_down(); let keys = hid.keys_down();

3
ctru-rs/src/services/am.rs

@ -6,6 +6,7 @@ use std::mem::MaybeUninit;
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]
#[repr(transparent)] #[repr(transparent)]
pub struct TitleInfo(ctru_sys::AM_TitleEntry); pub struct TitleInfo(ctru_sys::AM_TitleEntry);
impl TitleInfo { impl TitleInfo {
pub fn id(&self) -> u64 { pub fn id(&self) -> u64 {
self.0.titleID self.0.titleID
@ -61,7 +62,7 @@ impl<'a> Title<'a> {
pub struct Am(()); pub struct Am(());
impl Am { impl Am {
pub fn init() -> crate::Result<Am> { pub fn new() -> crate::Result<Am> {
unsafe { unsafe {
ResultCode(ctru_sys::amInit())?; ResultCode(ctru_sys::amInit())?;
Ok(Am(())) Ok(Am(()))

2
ctru-rs/src/services/apt.rs

@ -3,7 +3,7 @@ use crate::error::ResultCode;
pub struct Apt(()); pub struct Apt(());
impl Apt { impl Apt {
pub fn init() -> crate::Result<Apt> { pub fn new() -> crate::Result<Apt> {
unsafe { unsafe {
ResultCode(ctru_sys::aptInit())?; ResultCode(ctru_sys::aptInit())?;
Ok(Apt(())) Ok(Apt(()))

27
ctru-rs/src/services/cam.rs

@ -21,7 +21,7 @@ pub struct Cam {
} }
/// Flag to pass to [Camera::flip_image] /// Flag to pass to [Camera::flip_image]
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[repr(u32)] #[repr(u32)]
pub enum FlipMode { pub enum FlipMode {
None = ctru_sys::FLIP_NONE, None = ctru_sys::FLIP_NONE,
@ -31,7 +31,7 @@ pub enum FlipMode {
} }
/// Flag to pass to [Camera::set_view_size] /// Flag to pass to [Camera::set_view_size]
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[repr(u32)] #[repr(u32)]
pub enum ViewSize { pub enum ViewSize {
TopLCD = ctru_sys::SIZE_CTR_TOP_LCD, TopLCD = ctru_sys::SIZE_CTR_TOP_LCD,
@ -48,7 +48,7 @@ pub enum ViewSize {
} }
/// Flag to pass to [Camera::set_frame_rate] /// Flag to pass to [Camera::set_frame_rate]
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[repr(u32)] #[repr(u32)]
pub enum FrameRate { pub enum FrameRate {
Fps15 = ctru_sys::FRAME_RATE_15, Fps15 = ctru_sys::FRAME_RATE_15,
@ -68,7 +68,7 @@ pub enum FrameRate {
/// Flag to pass to [Camera::set_white_balance] or /// Flag to pass to [Camera::set_white_balance] or
/// [Camera::set_white_balance_without_base_up] /// [Camera::set_white_balance_without_base_up]
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[repr(u32)] #[repr(u32)]
pub enum WhiteBalance { pub enum WhiteBalance {
/// Normal /// Normal
@ -86,7 +86,7 @@ pub enum WhiteBalance {
} }
/// Flag to pass to [Camera::set_photo_mode] /// Flag to pass to [Camera::set_photo_mode]
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[repr(u32)] #[repr(u32)]
pub enum PhotoMode { pub enum PhotoMode {
Normal = ctru_sys::PHOTO_MODE_NORMAL, Normal = ctru_sys::PHOTO_MODE_NORMAL,
@ -97,7 +97,7 @@ pub enum PhotoMode {
} }
/// Flag to pass to [Camera::set_effect] /// Flag to pass to [Camera::set_effect]
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[repr(u32)] #[repr(u32)]
pub enum Effect { pub enum Effect {
None = ctru_sys::EFFECT_NONE, None = ctru_sys::EFFECT_NONE,
@ -109,7 +109,7 @@ pub enum Effect {
} }
/// Flag to pass to [Camera::set_contrast] /// Flag to pass to [Camera::set_contrast]
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[repr(u32)] #[repr(u32)]
pub enum Contrast { pub enum Contrast {
/// OFF /// OFF
@ -121,7 +121,7 @@ pub enum Contrast {
} }
/// Flag to pass to [Camera::set_lens_correction] /// Flag to pass to [Camera::set_lens_correction]
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[repr(u32)] #[repr(u32)]
pub enum LensCorrection { pub enum LensCorrection {
Off = ctru_sys::LENS_CORRECTION_DARK, Off = ctru_sys::LENS_CORRECTION_DARK,
@ -130,7 +130,7 @@ pub enum LensCorrection {
} }
/// Flag to pass to [Camera::set_output_format] /// Flag to pass to [Camera::set_output_format]
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[repr(u32)] #[repr(u32)]
pub enum OutputFormat { pub enum OutputFormat {
Yuv422 = ctru_sys::OUTPUT_YUV_422, Yuv422 = ctru_sys::OUTPUT_YUV_422,
@ -138,7 +138,7 @@ pub enum OutputFormat {
} }
/// Flag to pass to [Cam::play_shutter_sound] /// Flag to pass to [Cam::play_shutter_sound]
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[repr(u32)] #[repr(u32)]
pub enum ShutterSound { pub enum ShutterSound {
Normal = ctru_sys::SHUTTER_SOUND_TYPE_NORMAL, Normal = ctru_sys::SHUTTER_SOUND_TYPE_NORMAL,
@ -169,6 +169,7 @@ impl TryFrom<OutputFormat> for FramebufferFormat {
} }
/// Struct containing coordinates passed to [Camera::set_trimming_params]. /// Struct containing coordinates passed to [Camera::set_trimming_params].
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct TrimmingParams { pub struct TrimmingParams {
x_start: i16, x_start: i16,
y_start: i16, y_start: i16,
@ -193,11 +194,11 @@ impl TrimmingParams {
} }
/// Represents data used by the camera to calibrate image quality /// 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); pub struct ImageQualityCalibrationData(pub ctru_sys::CAMU_ImageQualityCalibrationData);
/// Represents data used by the camera to calibrate image quality when using both outward cameras /// 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); pub struct StereoCameraCalibrationData(pub ctru_sys::CAMU_StereoCameraCalibrationData);
/// Represents the camera on the inside of the 3DS /// 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. /// 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 /// Since this service requires no special or elevated permissions, errors are
/// rare in practice. /// rare in practice.
pub fn init() -> crate::Result<Cam> { pub fn new() -> crate::Result<Cam> {
unsafe { unsafe {
ResultCode(ctru_sys::camInit())?; ResultCode(ctru_sys::camInit())?;
Ok(Cam { Ok(Cam {

32
ctru-rs/src/services/cfgu.rs

@ -4,7 +4,7 @@
use crate::error::ResultCode; use crate::error::ResultCode;
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[repr(u32)] #[repr(u32)]
pub enum Region { pub enum Region {
Japan = ctru_sys::CFG_REGION_JPN, Japan = ctru_sys::CFG_REGION_JPN,
@ -16,7 +16,7 @@ pub enum Region {
Taiwan = ctru_sys::CFG_REGION_TWN, Taiwan = ctru_sys::CFG_REGION_TWN,
} }
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[repr(u32)] #[repr(u32)]
pub enum Language { pub enum Language {
Japanese = ctru_sys::CFG_LANGUAGE_JP, Japanese = ctru_sys::CFG_LANGUAGE_JP,
@ -33,15 +33,15 @@ pub enum Language {
TraditionalChinese = ctru_sys::CFG_LANGUAGE_TW, TraditionalChinese = ctru_sys::CFG_LANGUAGE_TW,
} }
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[repr(u32)] #[repr(u32)]
pub enum SystemModel { pub enum SystemModel {
Model3DS = ctru_sys::CFG_MODEL_3DS, Old3DS = ctru_sys::CFG_MODEL_3DS,
Model3DSXL = ctru_sys::CFG_MODEL_3DSXL, Old3DSXL = ctru_sys::CFG_MODEL_3DSXL,
ModelNew3DS = ctru_sys::CFG_MODEL_N3DS, New3DS = ctru_sys::CFG_MODEL_N3DS,
Model2DS = ctru_sys::CFG_MODEL_2DS, Old2DS = ctru_sys::CFG_MODEL_2DS,
ModelNew3DSXL = ctru_sys::CFG_MODEL_N3DSXL, New3DSXL = ctru_sys::CFG_MODEL_N3DSXL,
ModelNew2DSXL = ctru_sys::CFG_MODEL_N2DSXL, New2DSXL = ctru_sys::CFG_MODEL_N2DSXL,
} }
/// Represents the configuration service. No actions can be performed /// 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 /// ctrulib services are reference counted, so this function may be called
/// as many times as desired and the service will not exit until all /// as many times as desired and the service will not exit until all
/// instances of Cfgu drop out of scope. /// instances of Cfgu drop out of scope.
pub fn init() -> crate::Result<Cfgu> { pub fn new() -> crate::Result<Cfgu> {
ResultCode(unsafe { ctru_sys::cfguInit() })?; ResultCode(unsafe { ctru_sys::cfguInit() })?;
Ok(Cfgu(())) Ok(Cfgu(()))
} }
@ -163,12 +163,12 @@ impl TryFrom<u8> for SystemModel {
fn try_from(value: u8) -> Result<Self, Self::Error> { fn try_from(value: u8) -> Result<Self, Self::Error> {
match value as u32 { match value as u32 {
ctru_sys::CFG_MODEL_3DS => Ok(SystemModel::Model3DS), ctru_sys::CFG_MODEL_3DS => Ok(SystemModel::Old3DS),
ctru_sys::CFG_MODEL_3DSXL => Ok(SystemModel::Model3DSXL), ctru_sys::CFG_MODEL_3DSXL => Ok(SystemModel::Old3DSXL),
ctru_sys::CFG_MODEL_N3DS => Ok(SystemModel::ModelNew3DS), ctru_sys::CFG_MODEL_N3DS => Ok(SystemModel::New3DS),
ctru_sys::CFG_MODEL_2DS => Ok(SystemModel::Model2DS), ctru_sys::CFG_MODEL_2DS => Ok(SystemModel::Old2DS),
ctru_sys::CFG_MODEL_N3DSXL => Ok(SystemModel::ModelNew3DSXL), ctru_sys::CFG_MODEL_N3DSXL => Ok(SystemModel::New3DSXL),
ctru_sys::CFG_MODEL_N2DSXL => Ok(SystemModel::ModelNew2DSXL), ctru_sys::CFG_MODEL_N2DSXL => Ok(SystemModel::New2DSXL),
_ => Err(()), _ => Err(()),
} }
} }

33
ctru-rs/src/services/fs.rs

@ -23,17 +23,13 @@ bitflags! {
const FS_OPEN_WRITE = 2; const FS_OPEN_WRITE = 2;
const FS_OPEN_CREATE = 4; const FS_OPEN_CREATE = 4;
} }
}
bitflags! {
#[derive(Default)] #[derive(Default)]
struct FsWrite: u32 { struct FsWrite: u32 {
const FS_WRITE_FLUSH = 1; const FS_WRITE_FLUSH = 1;
const FS_WRITE_UPDATE_TIME = 256; const FS_WRITE_UPDATE_TIME = 256;
} }
}
bitflags! {
#[derive(Default)] #[derive(Default)]
struct FsAttribute: u32 { struct FsAttribute: u32 {
const FS_ATTRIBUTE_DIRECTORY = 1; const FS_ATTRIBUTE_DIRECTORY = 1;
@ -43,7 +39,7 @@ bitflags! {
} }
} }
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[repr(u32)] #[repr(u32)]
pub enum FsMediaType { pub enum FsMediaType {
Nand = ctru_sys::MEDIATYPE_NAND, Nand = ctru_sys::MEDIATYPE_NAND,
@ -51,7 +47,7 @@ pub enum FsMediaType {
GameCard = ctru_sys::MEDIATYPE_GAME_CARD, GameCard = ctru_sys::MEDIATYPE_GAME_CARD,
} }
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[repr(u32)] #[repr(u32)]
pub enum PathType { pub enum PathType {
Invalid = ctru_sys::PATH_INVALID, Invalid = ctru_sys::PATH_INVALID,
@ -61,7 +57,7 @@ pub enum PathType {
UTF16 = ctru_sys::PATH_UTF16, UTF16 = ctru_sys::PATH_UTF16,
} }
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[repr(u32)] #[repr(u32)]
pub enum ArchiveID { pub enum ArchiveID {
RomFS = ctru_sys::ARCHIVE_ROMFS, RomFS = ctru_sys::ARCHIVE_ROMFS,
@ -103,7 +99,7 @@ pub struct Fs(());
/// ```no_run /// ```no_run
/// use ctru::services::fs::Fs; /// use ctru::services::fs::Fs;
/// ///
/// let mut fs = Fs::init().unwrap(); /// let mut fs = Fs::new().unwrap();
/// let sdmc_archive = fs.sdmc().unwrap(); /// let sdmc_archive = fs.sdmc().unwrap();
/// ``` /// ```
pub struct Archive { pub struct Archive {
@ -129,11 +125,8 @@ pub struct Archive {
/// use std::io::prelude::*; /// use std::io::prelude::*;
/// use ctru::services::fs::{Fs, File}; /// use ctru::services::fs::{Fs, File};
/// ///
/// let mut fs = Fs::init()?; /// let mut fs = Fs::new()?;
/// let mut sdmc = fs.sdmc()?; /// let mut sdmc = fs.sdmc()?;
///
/// let mut file = File::create(&mut sdmc, "/foo.txt")?;
/// file.write_all(b"Hello, world!")?;
/// # /// #
/// # Ok(()) /// # Ok(())
/// # } /// # }
@ -148,7 +141,7 @@ pub struct Archive {
/// use std::io::prelude::*; /// use std::io::prelude::*;
/// use ctru::services::fs::{Fs, File}; /// use ctru::services::fs::{Fs, File};
/// ///
/// let mut fs = Fs::init()?; /// let mut fs = Fs::new()?;
/// let mut sdmc = fs.sdmc()?; /// let mut sdmc = fs.sdmc()?;
/// ///
/// let mut file = File::open(&sdmc, "/foo.txt")?; /// let mut file = File::open(&sdmc, "/foo.txt")?;
@ -171,7 +164,7 @@ pub struct Archive {
/// use std::io::prelude::*; /// use std::io::prelude::*;
/// use ctru::services::fs::{Fs, File}; /// use ctru::services::fs::{Fs, File};
/// ///
/// let mut fs = Fs::init()?; /// let mut fs = Fs::new()?;
/// let mut sdmc = fs.sdmc()?; /// let mut sdmc = fs.sdmc()?;
/// ///
/// let file = File::open(&sdmc, "/foo.txt")?; /// let file = File::open(&sdmc, "/foo.txt")?;
@ -227,7 +220,7 @@ pub struct Metadata {
/// ```no_run /// ```no_run
/// use ctru::services::fs::{Fs, OpenOptions}; /// 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 mut sdmc_archive = fs.sdmc().unwrap();
/// let file = OpenOptions::new() /// let file = OpenOptions::new()
/// .read(true) /// .read(true)
@ -242,7 +235,7 @@ pub struct Metadata {
/// ```no_run /// ```no_run
/// use ctru::services::fs::{Fs, OpenOptions}; /// 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 mut sdmc_archive = fs.sdmc().unwrap();
/// let file = OpenOptions::new() /// let file = OpenOptions::new()
/// .read(true) /// .read(true)
@ -252,7 +245,7 @@ pub struct Metadata {
/// .open("foo.txt") /// .open("foo.txt")
/// .unwrap(); /// .unwrap();
/// ``` /// ```
#[derive(Clone, Default)] #[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub struct OpenOptions { pub struct OpenOptions {
read: bool, read: bool,
write: bool, write: bool,
@ -316,7 +309,7 @@ impl Fs {
/// ctrulib services are reference counted, so this function may be called /// ctrulib services are reference counted, so this function may be called
/// as many times as desired and the service will not exit until all /// as many times as desired and the service will not exit until all
/// instances of Fs drop out of scope. /// instances of Fs drop out of scope.
pub fn init() -> crate::Result<Fs> { pub fn new() -> crate::Result<Fs> {
unsafe { unsafe {
let r = ctru_sys::fsInit(); let r = ctru_sys::fsInit();
if r < 0 { if r < 0 {
@ -369,7 +362,7 @@ impl File {
/// ```no_run /// ```no_run
/// use ctru::services::fs::{Fs, File}; /// 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 sdmc_archive = fs.sdmc().unwrap();
/// let mut f = File::open(&sdmc_archive, "/foo.txt").unwrap(); /// let mut f = File::open(&sdmc_archive, "/foo.txt").unwrap();
/// ``` /// ```
@ -398,7 +391,7 @@ impl File {
/// ```no_run /// ```no_run
/// use ctru::services::fs::{Fs, File}; /// 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 sdmc_archive = fs.sdmc().unwrap();
/// let mut f = File::create(&mut sdmc_archive, "/foo.txt").unwrap(); /// let mut f = File::create(&mut sdmc_archive, "/foo.txt").unwrap();
/// ``` /// ```

173
ctru-rs/src/services/gfx.rs

@ -9,11 +9,12 @@ use crate::services::gspgpu::{self, FramebufferFormat};
use crate::services::ServiceReference; use crate::services::ServiceReference;
mod private { mod private {
use super::{BottomScreen, TopScreen, TopScreenLeft, TopScreenRight}; use super::{BottomScreen, TopScreen, TopScreen3D, TopScreenLeft, TopScreenRight};
pub trait Sealed {} pub trait Sealed {}
impl Sealed for TopScreen {} impl Sealed for TopScreen {}
impl Sealed for TopScreen3D<'_> {}
impl Sealed for TopScreenLeft {} impl Sealed for TopScreenLeft {}
impl Sealed for TopScreenRight {} impl Sealed for TopScreenRight {}
impl Sealed for BottomScreen {} 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 /// Note that the pointer of the framebuffer returned by this function can
/// change after each call to this function if double buffering is enabled. /// change after each call to this function if double buffering is enabled.
fn raw_framebuffer(&mut self) -> RawFrameBuffer { fn raw_framebuffer(&mut self) -> RawFrameBuffer {
let mut width = 0; let mut width: u16 = 0;
let mut height = 0; let mut height: u16 = 0;
let ptr = unsafe { let ptr = unsafe {
ctru_sys::gfxGetFramebuffer(self.as_raw(), self.side().into(), &mut width, &mut height) ctru_sys::gfxGetFramebuffer(self.as_raw(), self.side().into(), &mut width, &mut height)
}; };
RawFrameBuffer { RawFrameBuffer {
ptr, ptr,
width, width: width.into(),
height, height: height.into(),
screen: PhantomData, screen: PhantomData,
} }
} }
/// Sets whether to use double buffering. Enabled by default. /// Sets whether to use double buffering. Enabled by default.
/// ///
/// Note that even when double buffering is disabled, one should still use the `swap_buffers` /// [`Swap::swap_buffers`] must be called after this function for the configuration
/// method on each frame to keep the gsp configuration up to date /// change to take effect.
fn set_double_buffering(&mut self, enabled: bool) { fn set_double_buffering(&mut self, enabled: bool) {
unsafe { ctru_sys::gfxSetDoubleBuffering(self.as_raw(), enabled) } unsafe { ctru_sys::gfxSetDoubleBuffering(self.as_raw(), enabled) }
} }
/// Gets the framebuffer format /// Gets the framebuffer format.
fn framebuffer_format(&self) -> FramebufferFormat { fn framebuffer_format(&self) -> FramebufferFormat {
unsafe { ctru_sys::gfxGetScreenFormat(self.as_raw()) }.into() 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) { fn set_framebuffer_format(&mut self, fmt: FramebufferFormat) {
unsafe { ctru_sys::gfxSetScreenFormat(self.as_raw(), fmt.into()) } 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 /// 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. /// converted into this, 3D mode will be enabled until this struct is dropped.
pub struct TopScreen3D<'top_screen> { pub struct TopScreen3D<'screen> {
screen: &'top_screen RefCell<TopScreen>, screen: &'screen RefCell<TopScreen>,
}
/// 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<S: Screen> 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] #[non_exhaustive]
pub struct TopScreenRight;
/// The bottom screen. Mutable access to this struct is required to write to the /// The bottom screen. Mutable access to this struct is required to write to the
/// bottom screen's frame buffer. /// bottom screen's frame buffer.
#[derive(Debug)]
#[non_exhaustive]
pub struct BottomScreen; pub struct BottomScreen;
/// Representation of a framebuffer for one [`Side`] of the top screen, or the /// 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. /// Pointer to graphics data to be rendered.
pub ptr: *mut u8, pub ptr: *mut u8,
/// The width of the framebuffer in pixels. /// The width of the framebuffer in pixels.
pub width: u16, pub width: usize,
/// The height of the framebuffer in pixels. /// 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. /// Keep a mutable reference to the Screen for which this framebuffer is tied.
screen: PhantomData<&'screen mut dyn Screen>, screen: PhantomData<&'screen mut dyn Screen>,
} }
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[repr(u32)] #[repr(u32)]
/// Side of top screen framebuffer /// Side of top screen framebuffer
/// ///
@ -128,10 +213,17 @@ pub struct Gfx {
static GFX_ACTIVE: Mutex<usize> = Mutex::new(0); static GFX_ACTIVE: Mutex<usize> = Mutex::new(0);
impl Gfx { 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<Self> {
Gfx::with_formats(FramebufferFormat::Bgr8, FramebufferFormat::Bgr8, false)
}
/// Initialize the Gfx module with the chosen framebuffer formats for the top and bottom /// Initialize the Gfx module with the chosen framebuffer formats for the top and bottom
/// screens /// 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( pub fn with_formats(
top_fb_fmt: FramebufferFormat, top_fb_fmt: FramebufferFormat,
bottom_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<Self> {
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 /// Waits for the vertical blank interrupt
/// ///
/// Use this to synchronize your application with the refresh rate of the LCD screens /// Use this to synchronize your application with the refresh rate of the LCD screens
@ -191,22 +257,20 @@ impl Gfx {
impl TopScreen3D<'_> { impl TopScreen3D<'_> {
/// Immutably borrow the two sides of the screen as `(left, right)`. /// Immutably borrow the two sides of the screen as `(left, right)`.
pub fn split(&self) -> (Ref<dyn Screen>, Ref<dyn Screen>) { pub fn split(&self) -> (Ref<TopScreenLeft>, Ref<TopScreenRight>) {
Ref::map_split(self.screen.borrow(), |screen| { Ref::map_split(self.screen.borrow(), |screen| (&screen.left, &screen.right))
(&screen.left as _, &screen.right as _)
})
} }
/// Mutably borrow the two sides of the screen as `(left, right)`. /// Mutably borrow the two sides of the screen as `(left, right)`.
pub fn split_mut(&self) -> (RefMut<dyn Screen>, RefMut<dyn Screen>) { pub fn split_mut(&self) -> (RefMut<TopScreenLeft>, RefMut<TopScreenRight>) {
RefMut::map_split(self.screen.borrow_mut(), |screen| { 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<TopScreen>> for TopScreen3D<'top_screen> { impl<'screen> From<&'screen RefCell<TopScreen>> for TopScreen3D<'screen> {
fn from(top_screen: &'top_screen RefCell<TopScreen>) -> Self { fn from(top_screen: &'screen RefCell<TopScreen>) -> Self {
unsafe { unsafe {
ctru_sys::gfxSet3D(true); ctru_sys::gfxSet3D(true);
} }
@ -232,6 +296,9 @@ impl TopScreen {
} }
/// Enable or disable wide mode on the top screen. /// 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) { pub fn set_wide_mode(&mut self, enable: bool) {
unsafe { unsafe {
ctru_sys::gfxSetWide(enable); 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 { impl Screen for TopScreen {
fn as_raw(&self) -> ctru_sys::gfxScreen_t { fn as_raw(&self) -> ctru_sys::gfxScreen_t {
self.left.as_raw() self.left.as_raw()
@ -294,6 +363,6 @@ mod tests {
#[test] #[test]
fn gfx_duplicate() { fn gfx_duplicate() {
// We don't need to build a `Gfx` because the test runner has one already // 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)));
} }
} }

4
ctru-rs/src/services/gspgpu.rs

@ -1,6 +1,6 @@
//! GSPGPU service //! GSPGPU service
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[repr(u32)] #[repr(u32)]
pub enum Event { pub enum Event {
Psc0 = ctru_sys::GSPGPU_EVENT_PSC0, Psc0 = ctru_sys::GSPGPU_EVENT_PSC0,
@ -13,7 +13,7 @@ pub enum Event {
} }
/// Framebuffer formats supported by the 3DS /// Framebuffer formats supported by the 3DS
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[repr(u32)] #[repr(u32)]
pub enum FramebufferFormat { pub enum FramebufferFormat {
/// RGBA8. 4 bytes per pixel /// RGBA8. 4 bytes per pixel

75
ctru-rs/src/services/hid.rs

@ -8,16 +8,15 @@ use crate::error::ResultCode;
bitflags::bitflags! { bitflags::bitflags! {
/// A set of flags corresponding to the button and directional pad /// A set of flags corresponding to the button and directional pad
/// inputs on the 3DS /// inputs on the 3DS
#[derive(Default)]
pub struct KeyPad: u32 { pub struct KeyPad: u32 {
const A = ctru_sys::KEY_A; const A = ctru_sys::KEY_A;
const B = ctru_sys::KEY_B; const B = ctru_sys::KEY_B;
const SELECT = ctru_sys::KEY_SELECT; const SELECT = ctru_sys::KEY_SELECT;
const START = ctru_sys::KEY_START; const START = ctru_sys::KEY_START;
const DRIGHT = ctru_sys::KEY_DRIGHT; const DPAD_RIGHT = ctru_sys::KEY_DRIGHT;
const DLEFT = ctru_sys::KEY_DLEFT; const DPAD_LEFT = ctru_sys::KEY_DLEFT;
const DUP = ctru_sys::KEY_DUP; const DPAD_UP = ctru_sys::KEY_DUP;
const DDOWN = ctru_sys::KEY_DDOWN; const DPAD_DOWN = ctru_sys::KEY_DDOWN;
const R = ctru_sys::KEY_R; const R = ctru_sys::KEY_R;
const L = ctru_sys::KEY_L; const L = ctru_sys::KEY_L;
const X = ctru_sys::KEY_X; const X = ctru_sys::KEY_X;
@ -34,10 +33,10 @@ bitflags::bitflags! {
const CPAD_UP = ctru_sys::KEY_CPAD_UP; const CPAD_UP = ctru_sys::KEY_CPAD_UP;
const CPAD_DOWN = ctru_sys::KEY_CPAD_DOWN; const CPAD_DOWN = ctru_sys::KEY_CPAD_DOWN;
// Convenience catch-all for the dpad and cpad // Convenience catch-all for the dpad and cpad
const UP = KeyPad::DUP.bits() | KeyPad::CPAD_UP.bits(); const UP = KeyPad::DPAD_UP.bits() | KeyPad::CPAD_UP.bits();
const DOWN = KeyPad::DDOWN.bits() | KeyPad::CPAD_DOWN.bits(); const DOWN = KeyPad::DPAD_DOWN.bits() | KeyPad::CPAD_DOWN.bits();
const LEFT = KeyPad::DLEFT.bits() | KeyPad::CPAD_LEFT.bits(); const LEFT = KeyPad::DPAD_LEFT.bits() | KeyPad::CPAD_LEFT.bits();
const RIGHT = KeyPad::DRIGHT.bits() | KeyPad::CPAD_RIGHT.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. /// This service requires no special permissions to use.
pub struct Hid(()); 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. /// Initializes the HID service.
/// ///
/// # Errors /// # Errors
@ -61,7 +54,7 @@ pub struct CirclePosition(ctru_sys::circlePosition);
/// Since this service requires no special or elevated permissions, errors are /// Since this service requires no special or elevated permissions, errors are
/// rare in practice. /// rare in practice.
impl Hid { impl Hid {
pub fn init() -> crate::Result<Hid> { pub fn new() -> crate::Result<Hid> {
unsafe { unsafe {
ResultCode(ctru_sys::hidInit())?; ResultCode(ctru_sys::hidInit())?;
Ok(Hid(())) Ok(Hid(()))
@ -101,47 +94,33 @@ impl Hid {
KeyPad::from_bits_truncate(keys) KeyPad::from_bits_truncate(keys)
} }
} }
}
impl Default for TouchPosition {
fn default() -> Self {
TouchPosition(ctru_sys::touchPosition { px: 0, py: 0 })
}
}
impl TouchPosition { /// Returns the current touch position in pixels (x, y).
/// Create a new TouchPosition instance. ///
pub fn new() -> Self { /// # Notes
Self::default() ///
} /// (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 { unsafe {
ctru_sys::hidTouchRead(&mut self.0); ctru_sys::hidTouchRead(&mut res);
} }
(self.0.px, self.0.py) (res.px, res.py)
}
}
impl Default for CirclePosition {
fn default() -> Self {
CirclePosition(ctru_sys::circlePosition { dx: 0, dy: 0 })
} }
}
impl CirclePosition { /// Returns the current circle pad position in relative (x, y).
/// Create a new CirclePosition instance. ///
pub fn new() -> Self { /// # Notes
Self::default() ///
} /// (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 { unsafe {
ctru_sys::hidCircleRead(&mut self.0); ctru_sys::hidCircleRead(&mut res);
} }
(self.0.dx, self.0.dy) (res.dx, res.dy)
} }
} }

12
ctru-rs/src/services/ndsp/mod.rs

@ -14,7 +14,7 @@ use std::sync::Mutex;
const NUMBER_OF_CHANNELS: u8 = 24; const NUMBER_OF_CHANNELS: u8 = 24;
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[repr(u32)] #[repr(u32)]
pub enum OutputMode { pub enum OutputMode {
Mono = ctru_sys::NDSP_OUTPUT_MONO, Mono = ctru_sys::NDSP_OUTPUT_MONO,
@ -22,7 +22,7 @@ pub enum OutputMode {
Surround = ctru_sys::NDSP_OUTPUT_SURROUND, Surround = ctru_sys::NDSP_OUTPUT_SURROUND,
} }
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[repr(u32)] #[repr(u32)]
pub enum AudioFormat { pub enum AudioFormat {
PCM8Mono = ctru_sys::NDSP_FORMAT_MONO_PCM8, PCM8Mono = ctru_sys::NDSP_FORMAT_MONO_PCM8,
@ -32,12 +32,12 @@ pub enum AudioFormat {
} }
/// Representation of volume mix for a channel. /// Representation of volume mix for a channel.
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug, PartialEq)]
pub struct AudioMix { pub struct AudioMix {
raw: [f32; 12], raw: [f32; 12],
} }
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[repr(u32)] #[repr(u32)]
pub enum InterpolationType { pub enum InterpolationType {
Polyphase = ctru_sys::NDSP_INTERP_POLYPHASE, Polyphase = ctru_sys::NDSP_INTERP_POLYPHASE,
@ -45,7 +45,7 @@ pub enum InterpolationType {
None = ctru_sys::NDSP_INTERP_NONE, None = ctru_sys::NDSP_INTERP_NONE,
} }
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum NdspError { pub enum NdspError {
/// Channel ID /// Channel ID
InvalidChannel(u8), InvalidChannel(u8),
@ -80,7 +80,7 @@ impl Ndsp {
/// ///
/// This function will return an error if an instance of the `Ndsp` struct already exists /// This function will return an error if an instance of the `Ndsp` struct already exists
/// or if there are any issues during initialization. /// or if there are any issues during initialization.
pub fn init() -> crate::Result<Self> { pub fn new() -> crate::Result<Self> {
let _service_handler = ServiceReference::new( let _service_handler = ServiceReference::new(
&NDSP_ACTIVE, &NDSP_ACTIVE,
false, false,

2
ctru-rs/src/services/ndsp/wave.rs

@ -11,7 +11,7 @@ pub struct Wave {
played_on_channel: Option<u8>, played_on_channel: Option<u8>,
} }
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[repr(u8)] #[repr(u8)]
/// Enum representing the playback status of a [Wave]. /// Enum representing the playback status of a [Wave].
pub enum WaveStatus { pub enum WaveStatus {

4
ctru-rs/src/services/ps.rs

@ -6,6 +6,7 @@
use crate::error::ResultCode; use crate::error::ResultCode;
use crate::Result; use crate::Result;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u32)] #[repr(u32)]
pub enum AESAlgorithm { pub enum AESAlgorithm {
CbcEnc = ctru_sys::PS_ALGORITHM_CBC_ENC, CbcEnc = ctru_sys::PS_ALGORITHM_CBC_ENC,
@ -16,6 +17,7 @@ pub enum AESAlgorithm {
CcmDec = ctru_sys::PS_ALGORITHM_CCM_DEC, CcmDec = ctru_sys::PS_ALGORITHM_CCM_DEC,
} }
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u32)] #[repr(u32)]
pub enum AESKeyType { pub enum AESKeyType {
Keyslot0D = ctru_sys::PS_KEYSLOT_0D, Keyslot0D = ctru_sys::PS_KEYSLOT_0D,
@ -56,7 +58,7 @@ impl Ps {
pub fn generate_random_bytes(&self, out: &mut [u8]) -> crate::Result<()> { pub fn generate_random_bytes(&self, out: &mut [u8]) -> crate::Result<()> {
ResultCode(unsafe { 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(()) Ok(())
} }

4
ctru-rs/src/services/romfs.rs

@ -25,7 +25,7 @@ pub struct RomFS {
static ROMFS_ACTIVE: Mutex<usize> = Mutex::new(0); static ROMFS_ACTIVE: Mutex<usize> = Mutex::new(0);
impl RomFS { impl RomFS {
pub fn init() -> crate::Result<Self> { pub fn new() -> crate::Result<Self> {
let _service_handler = ServiceReference::new( let _service_handler = ServiceReference::new(
&ROMFS_ACTIVE, &ROMFS_ACTIVE,
true, true,
@ -50,7 +50,7 @@ mod tests {
#[test] #[test]
fn romfs_counter() { fn romfs_counter() {
let _romfs = RomFS::init().unwrap(); let _romfs = RomFS::new().unwrap();
let value = *ROMFS_ACTIVE.lock().unwrap(); let value = *ROMFS_ACTIVE.lock().unwrap();
assert_eq!(value, 1); assert_eq!(value, 1);

6
ctru-rs/src/services/soc.rs

@ -25,7 +25,7 @@ impl Soc {
/// # Errors /// # Errors
/// ///
/// This function will return an error if the `Soc` service is already initialized /// This function will return an error if the `Soc` service is already initialized
pub fn init() -> crate::Result<Self> { pub fn new() -> crate::Result<Self> {
Self::init_with_buffer_size(0x100000) Self::init_with_buffer_size(0x100000)
} }
@ -107,8 +107,8 @@ mod tests {
#[test] #[test]
fn soc_duplicate() { 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)))
} }
} }

13
ctru-rs/src/services/sslc.rs

@ -8,23 +8,12 @@ pub struct SslC(());
impl SslC { impl SslC {
/// Initialize the service /// Initialize the service
pub fn init() -> crate::Result<Self> { pub fn new() -> crate::Result<Self> {
unsafe { unsafe {
ResultCode(ctru_sys::sslcInit(0))?; ResultCode(ctru_sys::sslcInit(0))?;
Ok(SslC(())) 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 { impl Drop for SslC {

10
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 /// 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). /// panic is just treated the same as any normal application panic).
pub(crate) fn run(tests: &[&TestDescAndFn]) { pub(crate) fn run(tests: &[&TestDescAndFn]) {
let gfx = Gfx::init().unwrap(); let gfx = Gfx::new().unwrap();
let mut hid = Hid::init().unwrap(); let mut hid = Hid::new().unwrap();
let apt = Apt::init().unwrap(); let apt = Apt::new().unwrap();
let mut top_screen = gfx.top_screen.borrow_mut(); let mut top_screen = gfx.top_screen.borrow_mut();
top_screen.set_wide_mode(true); top_screen.set_wide_mode(true);
let _console = Console::init(top_screen); let _console = Console::new(top_screen);
let opts = TestOpts { let opts = TestOpts {
force_run_in_process: true, force_run_in_process: true,
@ -39,8 +39,6 @@ pub(crate) fn run(tests: &[&TestDescAndFn]) {
println!("Press START to exit."); println!("Press START to exit.");
while apt.main_loop() { while apt.main_loop() {
gfx.flush_buffers();
gfx.swap_buffers();
gfx.wait_for_vblank(); gfx.wait_for_vblank();
hid.scan_input(); hid.scan_input();

Loading…
Cancel
Save