Andrea Ciliberti
2 years ago
3 changed files with 83 additions and 0 deletions
@ -0,0 +1,43 @@
@@ -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 @@
@@ -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