AzureMarker
3 years ago
6 changed files with 202 additions and 0 deletions
@ -1,3 +1,6 @@
@@ -1,3 +1,6 @@
|
||||
target |
||||
Cargo.lock |
||||
.cargo |
||||
|
||||
# IDE files |
||||
.idea |
||||
|
@ -0,0 +1,73 @@
@@ -0,0 +1,73 @@
|
||||
//! This example runs a basic future executor from the `futures` library.
|
||||
//! Every 60 frames (about 1 second) it prints "Tick" to the console.
|
||||
//! The executor runs on a separate thread. Internally it yields when it has no more work to do,
|
||||
//! allowing other threads to run.
|
||||
//! The example also implements clean shutdown by using a oneshot channel to end the future, thus
|
||||
//! ending the executor and the thread it runs on.
|
||||
|
||||
use ctru::console::Console; |
||||
use ctru::services::hid::KeyPad; |
||||
use ctru::services::{Apt, Hid}; |
||||
use ctru::Gfx; |
||||
use futures::StreamExt; |
||||
|
||||
fn main() { |
||||
ctru::init(); |
||||
let gfx = Gfx::default(); |
||||
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()); |
||||
|
||||
// Give ourselves up to 30% of the system core's time
|
||||
apt.set_app_cpu_time_limit(30) |
||||
.expect("Failed to enable system core"); |
||||
|
||||
println!("Starting executor..."); |
||||
|
||||
let (exit_sender, mut exit_receiver) = futures::channel::oneshot::channel(); |
||||
let (mut timer_sender, mut timer_receiver) = futures::channel::mpsc::channel(0); |
||||
let executor_thread = ctru::thread::Builder::new() |
||||
.affinity(1) |
||||
.spawn(move || { |
||||
let mut executor = futures::executor::LocalPool::new(); |
||||
|
||||
executor.run_until(async move { |
||||
loop { |
||||
futures::select! { |
||||
_ = exit_receiver => break, |
||||
_ = timer_receiver.next() => { |
||||
println!("Tick"); |
||||
} |
||||
} |
||||
} |
||||
}); |
||||
}) |
||||
.expect("Failed to create executor thread"); |
||||
|
||||
println!("Executor started!"); |
||||
|
||||
let mut frame_count = 0; |
||||
while apt.main_loop() { |
||||
hid.scan_input(); |
||||
|
||||
if hid.keys_down().contains(KeyPad::KEY_START) { |
||||
println!("Shutting down..."); |
||||
let _ = exit_sender.send(()); |
||||
let _ = executor_thread.join(); |
||||
break; |
||||
} |
||||
|
||||
frame_count += 1; |
||||
|
||||
if frame_count == 60 { |
||||
if let Err(e) = timer_sender.try_send(()) { |
||||
println!("Error sending timer message: {e}"); |
||||
} |
||||
frame_count = 0; |
||||
} |
||||
|
||||
gfx.flush_buffers(); |
||||
gfx.swap_buffers(); |
||||
gfx.wait_for_vblank(); |
||||
} |
||||
} |
@ -0,0 +1,39 @@
@@ -0,0 +1,39 @@
|
||||
use ctru::console::Console; |
||||
use ctru::gfx::Gfx; |
||||
use ctru::services::apt::Apt; |
||||
use ctru::services::hid::{Hid, KeyPad}; |
||||
use ctru::services::ps::Ps; |
||||
|
||||
fn main() { |
||||
// Initialize services
|
||||
ctru::init(); |
||||
let apt = Apt::init().unwrap(); |
||||
let hid = Hid::init().unwrap(); |
||||
let gfx = Gfx::default(); |
||||
let _console = Console::init(gfx.top_screen.borrow_mut()); |
||||
|
||||
// HashMaps generate hashes thanks to the 3DS' criptografically secure generator.
|
||||
// Sadly, this generator is only active when activating the `Ps` service.
|
||||
// To do this, we have to make sure the `Ps` service handle is alive for the whole
|
||||
// run time (or at least, when `HashMaps` are used).
|
||||
// Not having a living `Ps` instance when using `HashMap`s results in a panic
|
||||
let _ps = Ps::init().unwrap(); |
||||
|
||||
let mut map = std::collections::HashMap::new(); |
||||
map.insert("A Key!", 102); |
||||
map.insert("Another key?", 543); |
||||
map.remove("A Key!"); |
||||
|
||||
println!("{:#?}", map); |
||||
|
||||
while apt.main_loop() { |
||||
gfx.flush_buffers(); |
||||
gfx.swap_buffers(); |
||||
gfx.wait_for_vblank(); |
||||
|
||||
hid.scan_input(); |
||||
if hid.keys_down().contains(KeyPad::KEY_START) { |
||||
break; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,85 @@
@@ -0,0 +1,85 @@
|
||||
//! Process Services (PS) module. This is used for miscellaneous utility tasks, but
|
||||
//! is particularly important because it is used to generate random data, which
|
||||
//! is required for common things like [`HashMap`](std::collections::HashMap).
|
||||
//! See also <https://www.3dbrew.org/wiki/Process_Services>
|
||||
|
||||
/// PS handle. This must not be dropped in order for random generation
|
||||
/// to work (in most cases, the lifetime of an application).
|
||||
#[non_exhaustive] |
||||
pub struct Ps; |
||||
|
||||
#[repr(u32)] |
||||
pub enum AESAlgorithm { |
||||
CbcEnc, |
||||
CbcDec, |
||||
CtrEnc, |
||||
CtrDec, |
||||
CcmEnc, |
||||
CcmDec, |
||||
} |
||||
|
||||
#[repr(u32)] |
||||
pub enum AESKeyType { |
||||
Keyslot0D, |
||||
Keyslot2D, |
||||
Keyslot31, |
||||
Keyslot38, |
||||
Keyslot32, |
||||
Keyslot39Dlp, |
||||
Keyslot2E, |
||||
KeyslotInvalid, |
||||
Keyslot36, |
||||
Keyslot39Nfc, |
||||
} |
||||
|
||||
impl Ps { |
||||
/// Initialize the PS module.
|
||||
pub fn init() -> crate::Result<Self> { |
||||
let r = unsafe { ctru_sys::psInit() }; |
||||
if r < 0 { |
||||
Err(r.into()) |
||||
} else { |
||||
Ok(Self) |
||||
} |
||||
} |
||||
|
||||
pub fn local_friend_code_seed(&self) -> crate::Result<u64> { |
||||
let mut seed: u64 = 0; |
||||
|
||||
let r = unsafe { ctru_sys::PS_GetLocalFriendCodeSeed(&mut seed) }; |
||||
if r < 0 { |
||||
Err(r.into()) |
||||
} else { |
||||
Ok(seed) |
||||
} |
||||
} |
||||
|
||||
pub fn device_id(&self) -> crate::Result<u32> { |
||||
let mut id: u32 = 0; |
||||
|
||||
let r = unsafe { ctru_sys::PS_GetDeviceId(&mut id) }; |
||||
if r < 0 { |
||||
Err(r.into()) |
||||
} else { |
||||
Ok(id) |
||||
} |
||||
} |
||||
|
||||
pub fn generate_random_bytes(&self, out: &mut [u8]) -> crate::Result<()> { |
||||
let r = |
||||
unsafe { ctru_sys::PS_GenerateRandomBytes(out as *mut _ as *mut _, out.len() as u32) }; |
||||
if r < 0 { |
||||
Err(r.into()) |
||||
} else { |
||||
Ok(()) |
||||
} |
||||
} |
||||
} |
||||
|
||||
impl Drop for Ps { |
||||
fn drop(&mut self) { |
||||
unsafe { |
||||
ctru_sys::psExit(); |
||||
} |
||||
} |
||||
} |
Loading…
Reference in new issue