From 39467960ef2c1f32d0d140347984e6470768fffc Mon Sep 17 00:00:00 2001 From: Andrea Ciliberti Date: Tue, 22 Nov 2022 11:11:18 +0100 Subject: [PATCH 1/6] Add LINEAR allocator module --- ctru-rs/examples/linear-memory.rs | 43 +++++++++++++++++++++++++++++++ ctru-rs/src/lib.rs | 2 ++ ctru-rs/src/linear.rs | 38 +++++++++++++++++++++++++++ 3 files changed, 83 insertions(+) create mode 100644 ctru-rs/examples/linear-memory.rs create mode 100644 ctru-rs/src/linear.rs diff --git a/ctru-rs/examples/linear-memory.rs b/ctru-rs/examples/linear-memory.rs new file mode 100644 index 0000000..96ec554 --- /dev/null +++ b/ctru-rs/examples/linear-memory.rs @@ -0,0 +1,43 @@ +#![feature(allocator_api)] + +use ctru::prelude::*; +use ctru::linear::LinearAllocator; + +fn main() { + ctru::init(); + let gfx = Gfx::init().expect("Couldn't obtain GFX controller"); + let 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 linear_space_before = LinearAllocator::free_space(); + + // Normal `Box` on the heap + let heap_box = Box::new(1492); + // `Box` living on the linear memory sector + let linear_box: Box:: = Box::new_in(2022, LinearAllocator); + + println!("This value is from the heap: {heap_box}"); + println!("This value is from the LINEAR memory: {linear_box}"); + + println!("\nLINEAR space free before allocation: {linear_space_before}"); + println!("LINEAR space free after allocation: {}", LinearAllocator::free_space()); + + println!("\x1b[29;16HPress Start to exit"); + + // 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::KEY_START) { + break; + } + // Flush and swap framebuffers + gfx.flush_buffers(); + gfx.swap_buffers(); + + //Wait for VBlank + gfx.wait_for_vblank(); + } +} diff --git a/ctru-rs/src/lib.rs b/ctru-rs/src/lib.rs index 264d0ef..35fdc0c 100644 --- a/ctru-rs/src/lib.rs +++ b/ctru-rs/src/lib.rs @@ -3,6 +3,7 @@ #![feature(test)] #![feature(custom_test_frameworks)] #![feature(try_trait_v2)] +#![feature(allocator_api)] #![test_runner(test_runner::run)] extern "C" fn services_deinit() { @@ -76,6 +77,7 @@ pub mod applets; pub mod console; pub mod error; pub mod gfx; +pub mod linear; pub mod prelude; pub mod services; diff --git a/ctru-rs/src/linear.rs b/ctru-rs/src/linear.rs new file mode 100644 index 0000000..88f65fe --- /dev/null +++ b/ctru-rs/src/linear.rs @@ -0,0 +1,38 @@ +//! Linear memory allocator +//! +//! Linear memory is a sector of the 3DS' RAM that binds virtual addresses exactly to the physical address. +//! As such, it is used for fast and safe memory sharing between services (and is especially needed for GPU and DSP). +//! +//! Resources:
+//!
+//! + +use std::alloc::Allocator; + +// Implementing an `std::alloc::Allocator` type is the best way to handle this case, since it gives +// us full control over the normal `std` implementations (like `Box`). The only issue is that this is another unstable feature to add. +// Sadly the linear memory allocator included in `libctru` doesn't implement `linearRealloc` at the time of these additions, +// but the default fallback of the `std` will take care of that for us. + +/// [`std::alloc::Allocator`] struct for LINEAR memory +pub struct LinearAllocator; + +impl LinearAllocator { + /// Returns the amount of free space left in the LINEAR sector + pub fn free_space() -> u32 { + unsafe { ctru_sys::linearSpaceFree() } + } +} + +unsafe impl Allocator for LinearAllocator { + fn allocate(&self, layout: std::alloc::Layout) -> Result, std::alloc::AllocError> { + let pointer = unsafe { ctru_sys::linearAlloc(layout.size() as u32) }; + let slice: &mut [u8] = unsafe { std::slice::from_raw_parts_mut(pointer as *mut u8, layout.size()) }; + + std::ptr::NonNull::new(slice).ok_or(std::alloc::AllocError) + } + + unsafe fn deallocate(&self, ptr: std::ptr::NonNull, _layout: std::alloc::Layout) { + unsafe { ctru_sys::linearFree(ptr.as_ptr() as *mut _) }; + } +} From be858ff6aeb30ddec03924257994d99a0e911d47 Mon Sep 17 00:00:00 2001 From: Andrea Ciliberti Date: Tue, 22 Nov 2022 11:29:07 +0100 Subject: [PATCH 2/6] Cargo fmt --- ctru-rs/examples/linear-memory.rs | 9 ++++++--- ctru-rs/src/linear.rs | 12 ++++++++---- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/ctru-rs/examples/linear-memory.rs b/ctru-rs/examples/linear-memory.rs index 96ec554..11d13d3 100644 --- a/ctru-rs/examples/linear-memory.rs +++ b/ctru-rs/examples/linear-memory.rs @@ -1,7 +1,7 @@ #![feature(allocator_api)] -use ctru::prelude::*; use ctru::linear::LinearAllocator; +use ctru::prelude::*; fn main() { ctru::init(); @@ -15,13 +15,16 @@ fn main() { // Normal `Box` on the heap let heap_box = Box::new(1492); // `Box` living on the linear memory sector - let linear_box: Box:: = Box::new_in(2022, LinearAllocator); + let linear_box: Box = Box::new_in(2022, LinearAllocator); println!("This value is from the heap: {heap_box}"); println!("This value is from the LINEAR memory: {linear_box}"); println!("\nLINEAR space free before allocation: {linear_space_before}"); - println!("LINEAR space free after allocation: {}", LinearAllocator::free_space()); + println!( + "LINEAR space free after allocation: {}", + LinearAllocator::free_space() + ); println!("\x1b[29;16HPress Start to exit"); diff --git a/ctru-rs/src/linear.rs b/ctru-rs/src/linear.rs index 88f65fe..507cacd 100644 --- a/ctru-rs/src/linear.rs +++ b/ctru-rs/src/linear.rs @@ -2,7 +2,7 @@ //! //! Linear memory is a sector of the 3DS' RAM that binds virtual addresses exactly to the physical address. //! As such, it is used for fast and safe memory sharing between services (and is especially needed for GPU and DSP). -//! +//! //! Resources:
//!
//! @@ -25,10 +25,14 @@ impl LinearAllocator { } unsafe impl Allocator for LinearAllocator { - fn allocate(&self, layout: std::alloc::Layout) -> Result, std::alloc::AllocError> { + fn allocate( + &self, + layout: std::alloc::Layout, + ) -> Result, std::alloc::AllocError> { let pointer = unsafe { ctru_sys::linearAlloc(layout.size() as u32) }; - let slice: &mut [u8] = unsafe { std::slice::from_raw_parts_mut(pointer as *mut u8, layout.size()) }; - + let slice: &mut [u8] = + unsafe { std::slice::from_raw_parts_mut(pointer as *mut u8, layout.size()) }; + std::ptr::NonNull::new(slice).ok_or(std::alloc::AllocError) } From e2dd1335d4b531af302ad49ffacb093005bc2ddc Mon Sep 17 00:00:00 2001 From: Andrea Ciliberti Date: Tue, 22 Nov 2022 11:36:42 +0100 Subject: [PATCH 3/6] Fix issues of the CI --- ctru-rs/src/linear.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ctru-rs/src/linear.rs b/ctru-rs/src/linear.rs index 507cacd..8a68de6 100644 --- a/ctru-rs/src/linear.rs +++ b/ctru-rs/src/linear.rs @@ -37,6 +37,6 @@ unsafe impl Allocator for LinearAllocator { } unsafe fn deallocate(&self, ptr: std::ptr::NonNull, _layout: std::alloc::Layout) { - unsafe { ctru_sys::linearFree(ptr.as_ptr() as *mut _) }; + ctru_sys::linearFree(ptr.as_ptr() as *mut _); } } From 4d196760ee3aef866ea949253fd9547c80cba9cd Mon Sep 17 00:00:00 2001 From: Andrea Ciliberti Date: Wed, 23 Nov 2022 16:24:34 +0100 Subject: [PATCH 4/6] Fix alignment and follow suggestions --- ctru-rs/src/lib.rs | 1 + ctru-rs/src/linear.rs | 18 ++++++++++-------- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/ctru-rs/src/lib.rs b/ctru-rs/src/lib.rs index 8439531..490b268 100644 --- a/ctru-rs/src/lib.rs +++ b/ctru-rs/src/lib.rs @@ -4,6 +4,7 @@ #![feature(custom_test_frameworks)] #![feature(try_trait_v2)] #![feature(allocator_api)] +#![feature(nonnull_slice_from_raw_parts)] #![test_runner(test_runner::run)] extern "C" fn services_deinit() { diff --git a/ctru-rs/src/linear.rs b/ctru-rs/src/linear.rs index 8a68de6..b9ee0e4 100644 --- a/ctru-rs/src/linear.rs +++ b/ctru-rs/src/linear.rs @@ -7,7 +7,8 @@ //!
//! -use std::alloc::Allocator; +use std::alloc::{Allocator, AllocError, Layout}; +use std::ptr::NonNull; // Implementing an `std::alloc::Allocator` type is the best way to handle this case, since it gives // us full control over the normal `std` implementations (like `Box`). The only issue is that this is another unstable feature to add. @@ -15,6 +16,7 @@ use std::alloc::Allocator; // but the default fallback of the `std` will take care of that for us. /// [`std::alloc::Allocator`] struct for LINEAR memory +/// To use this struct the main crate must activate the `allocator_api` unstable feature. pub struct LinearAllocator; impl LinearAllocator { @@ -27,16 +29,16 @@ impl LinearAllocator { unsafe impl Allocator for LinearAllocator { fn allocate( &self, - layout: std::alloc::Layout, - ) -> Result, std::alloc::AllocError> { - let pointer = unsafe { ctru_sys::linearAlloc(layout.size() as u32) }; - let slice: &mut [u8] = - unsafe { std::slice::from_raw_parts_mut(pointer as *mut u8, layout.size()) }; + layout: Layout, + ) -> Result, AllocError> { + let pointer = unsafe { ctru_sys::linearMemAlign(layout.size() as u32, layout.align() as u32) }; - std::ptr::NonNull::new(slice).ok_or(std::alloc::AllocError) + NonNull::new(pointer.cast()) + .map(|ptr| NonNull::slice_from_raw_parts(ptr, layout.size())) + .ok_or(AllocError) } - unsafe fn deallocate(&self, ptr: std::ptr::NonNull, _layout: std::alloc::Layout) { + unsafe fn deallocate(&self, ptr: NonNull, _layout: Layout) { ctru_sys::linearFree(ptr.as_ptr() as *mut _); } } From c2c14b949b213456440779570b56914675c2f560 Mon Sep 17 00:00:00 2001 From: Andrea Ciliberti Date: Wed, 23 Nov 2022 16:27:06 +0100 Subject: [PATCH 5/6] Fixed deallocate types --- ctru-rs/src/linear.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ctru-rs/src/linear.rs b/ctru-rs/src/linear.rs index b9ee0e4..a913f27 100644 --- a/ctru-rs/src/linear.rs +++ b/ctru-rs/src/linear.rs @@ -39,6 +39,6 @@ unsafe impl Allocator for LinearAllocator { } unsafe fn deallocate(&self, ptr: NonNull, _layout: Layout) { - ctru_sys::linearFree(ptr.as_ptr() as *mut _); + ctru_sys::linearFree(ptr.as_ptr().cast()); } } From 8594268fc2d77bce3d76228cd32a5e2d49fbaad5 Mon Sep 17 00:00:00 2001 From: Andrea Ciliberti Date: Wed, 23 Nov 2022 16:29:06 +0100 Subject: [PATCH 6/6] Cargo fmt --- ctru-rs/src/linear.rs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/ctru-rs/src/linear.rs b/ctru-rs/src/linear.rs index a913f27..da91eb7 100644 --- a/ctru-rs/src/linear.rs +++ b/ctru-rs/src/linear.rs @@ -7,7 +7,7 @@ //!
//! -use std::alloc::{Allocator, AllocError, Layout}; +use std::alloc::{AllocError, Allocator, Layout}; use std::ptr::NonNull; // Implementing an `std::alloc::Allocator` type is the best way to handle this case, since it gives @@ -27,11 +27,9 @@ impl LinearAllocator { } unsafe impl Allocator for LinearAllocator { - fn allocate( - &self, - layout: Layout, - ) -> Result, AllocError> { - let pointer = unsafe { ctru_sys::linearMemAlign(layout.size() as u32, layout.align() as u32) }; + fn allocate(&self, layout: Layout) -> Result, AllocError> { + let pointer = + unsafe { ctru_sys::linearMemAlign(layout.size() as u32, layout.align() as u32) }; NonNull::new(pointer.cast()) .map(|ptr| NonNull::slice_from_raw_parts(ptr, layout.size()))