Browse Source

Merge pull request #81 from rust3ds/feature/linear-alloc

Add LINEAR allocator module
pull/84/head
Meziu 2 years ago committed by GitHub
parent
commit
1b6b4ebc6d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 46
      ctru-rs/examples/linear-memory.rs
  2. 3
      ctru-rs/src/lib.rs
  3. 42
      ctru-rs/src/linear.rs

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

@ -0,0 +1,46 @@
#![feature(allocator_api)]
use ctru::linear::LinearAllocator;
use ctru::prelude::*;
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();
}
}

3
ctru-rs/src/lib.rs

@ -3,6 +3,8 @@
#![feature(test)] #![feature(test)]
#![feature(custom_test_frameworks)] #![feature(custom_test_frameworks)]
#![feature(try_trait_v2)] #![feature(try_trait_v2)]
#![feature(allocator_api)]
#![feature(nonnull_slice_from_raw_parts)]
#![test_runner(test_runner::run)] #![test_runner(test_runner::run)]
extern "C" fn services_deinit() { extern "C" fn services_deinit() {
@ -76,6 +78,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 mii; pub mod mii;
pub mod prelude; pub mod prelude;
pub mod services; pub mod services;

42
ctru-rs/src/linear.rs

@ -0,0 +1,42 @@
//! 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::{AllocError, Allocator, 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.
// 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
/// To use this struct the main crate must activate the `allocator_api` unstable feature.
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: Layout) -> Result<NonNull<[u8]>, 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()))
.ok_or(AllocError)
}
unsafe fn deallocate(&self, ptr: NonNull<u8>, _layout: Layout) {
ctru_sys::linearFree(ptr.as_ptr().cast());
}
}
Loading…
Cancel
Save