Browse Source

Add LINEAR allocator module

pull/81/head
Andrea Ciliberti 2 years ago
parent
commit
39467960ef
  1. 43
      ctru-rs/examples/linear-memory.rs
  2. 2
      ctru-rs/src/lib.rs
  3. 38
      ctru-rs/src/linear.rs

43
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::<i32, LinearAllocator> = 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();
}
}

2
ctru-rs/src/lib.rs

@ -3,6 +3,7 @@
#![feature(test)] #![feature(test)]
#![feature(custom_test_frameworks)] #![feature(custom_test_frameworks)]
#![feature(try_trait_v2)] #![feature(try_trait_v2)]
#![feature(allocator_api)]
#![test_runner(test_runner::run)] #![test_runner(test_runner::run)]
extern "C" fn services_deinit() { extern "C" fn services_deinit() {
@ -76,6 +77,7 @@ pub mod applets;
pub mod console; pub mod console;
pub mod error; pub mod error;
pub mod gfx; pub mod gfx;
pub mod linear;
pub mod prelude; pub mod prelude;
pub mod services; pub mod services;

38
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:<br>
//! <https://github.com/devkitPro/libctru/blob/master/libctru/source/allocator/linear.cpp><br>
//! <https://www.3dbrew.org/wiki/Memory_layout>
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::ptr::NonNull<[u8]>, 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<u8>, _layout: std::alloc::Layout) {
unsafe { ctru_sys::linearFree(ptr.as_ptr() as *mut _) };
}
}
Loading…
Cancel
Save