Andrea Ciliberti
2 years ago
3 changed files with 83 additions and 0 deletions
@ -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(); |
||||||
|
} |
||||||
|
} |
@ -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…
Reference in new issue