Browse Source

Add more functionality to `Am` service wrapper and improve title-info.rs

pull/95/head
Maccraft123 2 years ago
parent
commit
3ad9780d4c
  1. 98
      ctru-rs/examples/title-info.rs
  2. 56
      ctru-rs/src/services/am.rs

98
ctru-rs/examples/title-info.rs

@ -9,19 +9,26 @@ fn main() {
let hid = Hid::init().expect("Couldn't obtain HID controller"); let hid = Hid::init().expect("Couldn't obtain HID controller");
let apt = Apt::init().expect("Couldn't obtain APT controller"); let apt = Apt::init().expect("Couldn't obtain APT controller");
let am = Am::init().expect("Couldn't obtain AM controller"); let am = Am::init().expect("Couldn't obtain AM controller");
let _console = Console::init(gfx.top_screen.borrow_mut()); let top_screen = Console::init(gfx.top_screen.borrow_mut());
let bottom_screen = Console::init(gfx.bottom_screen.borrow_mut());
let title_count = am let sd_count = am
.get_title_count(FsMediaType::Sd) .get_title_count(FsMediaType::Sd)
.expect("Failed to get title count"); .expect("Failed to get sd title count");
println!("This 3DS has {title_count} titles on its SD Card:"); let sd_list = am
let title_list = am
.get_title_list(FsMediaType::Sd) .get_title_list(FsMediaType::Sd)
.expect("Failed to get title list"); .expect("Failed to get sd title list");
for id in title_list {
println!("{id:x}"); let nand_count = am
} .get_title_count(FsMediaType::Nand)
.expect("Failed to get nand title count");
let nand_list = am
.get_title_list(FsMediaType::Nand)
.expect("Failed to get nand title list");
let mut offset = 0;
let mut refresh = true;
let mut use_nand = false;
// Main loop // Main loop
while apt.main_loop() { while apt.main_loop() {
@ -31,6 +38,77 @@ fn main() {
if hid.keys_down().contains(KeyPad::KEY_START) { if hid.keys_down().contains(KeyPad::KEY_START) {
break; break;
} }
if hid.keys_down().contains(KeyPad::KEY_SELECT) {
refresh = true;
offset = 0;
use_nand = !use_nand;
}
let cur_list = if use_nand { &nand_list } else { &sd_list };
if hid.keys_down().intersects(KeyPad::KEY_DOWN) {
if offset + 1 < cur_list.len() {
offset = offset + 1;
refresh = true;
}
} else if hid.keys_down().intersects(KeyPad::KEY_UP) {
if offset > 0 {
offset = offset - 1;
refresh = true;
}
}
if refresh {
let mut selected_title = 0;
// Clear top screen and write title ids to it
top_screen.select();
print!("\x1b[2J");
// Top screen seems to have only 30 rows
for (i, id) in cur_list.iter().skip(offset).take(29).enumerate() {
if i == 0 {
selected_title = *id;
println!("=> {id:x}");
} else {
println!(" {id:x}");
}
}
// Clear bottom screen and write properties of selected title to it
bottom_screen.select();
println!("\x1b[2J");
// Move cursor to top left
println!("\x1b[1;1");
let media = if use_nand {
FsMediaType::Nand
} else {
FsMediaType::Sd
};
match am.get_title_info(media, &mut [selected_title]) {
Ok(info) => {
// Vec returned by Am::get_title_info always has same length as inputed slice
let info = info[0];
println!("Size: {} KB", info.size_bytes() / 1024);
println!("Version: 0x{:x}", info.version());
println!("Type: 0x{:x}", info.type_());
}
Err(e) => println!("Failed to get title info: {}", e),
}
println!("\x1b[26;0HPress START to exit");
if use_nand {
println!("Press SELECT to choose SD Card");
println!("Current medium: NAND");
println!("Title count: {}", nand_count);
} else {
println!("Press SELECT to choose NAND");
println!("Current medium: SD Card");
println!("Title count: {}", sd_count);
}
refresh = false;
}
// Flush and swap framebuffers // Flush and swap framebuffers
gfx.flush_buffers(); gfx.flush_buffers();
gfx.swap_buffers(); gfx.swap_buffers();

56
ctru-rs/src/services/am.rs

@ -1,6 +1,34 @@
use crate::error::ResultCode; use crate::error::ResultCode;
use crate::services::fs::FsMediaType; use crate::services::fs::FsMediaType;
#[derive(Copy, Clone, Debug)]
#[repr(C)]
pub struct TitleInfo {
id: u64,
size: u64,
version: u16,
pad: u16,
type_: u32,
}
// Make sure TitleInfo is correct size
const _TITLEINFO_SIZE_CHECK: [u8; 0x18] = [0; std::mem::size_of::<TitleInfo>()];
impl TitleInfo {
pub fn id(&self) -> u64 {
self.id
}
pub fn size_bytes(&self) -> u64 {
self.size
}
pub fn version(&self) -> u16 {
self.version
}
pub fn type_(&self) -> u32 {
self.type_
}
}
pub struct Am(()); pub struct Am(());
impl Am { impl Am {
@ -20,11 +48,10 @@ impl Am {
} }
pub fn get_title_list(&self, mediatype: FsMediaType) -> crate::Result<Vec<u64>> { pub fn get_title_list(&self, mediatype: FsMediaType) -> crate::Result<Vec<u64>> {
let count = self.get_title_count(mediatype)?;
let mut buf = Vec::with_capacity(count as usize);
let mut read_amount = 0;
unsafe { unsafe {
let count = self.get_title_count(mediatype)?;
let mut buf = Vec::with_capacity(count as usize);
let mut read_amount = 0;
ResultCode(ctru_sys::AM_GetTitleList( ResultCode(ctru_sys::AM_GetTitleList(
&mut read_amount, &mut read_amount,
mediatype as u32, mediatype as u32,
@ -33,8 +60,27 @@ impl Am {
))?; ))?;
buf.set_len(read_amount as usize); buf.set_len(read_amount as usize);
Ok(buf)
} }
Ok(buf)
}
pub fn get_title_info(
&self,
mediatype: FsMediaType,
id_list: &mut [u64],
) -> crate::Result<Vec<TitleInfo>> {
let mut info = Vec::with_capacity(id_list.len());
unsafe {
ResultCode(ctru_sys::AM_GetTitleInfo(
mediatype as u32,
id_list.len() as u32,
id_list.as_mut_ptr(),
info.as_mut_ptr() as _,
))?;
info.set_len(id_list.len());
}
Ok(info)
} }
} }

Loading…
Cancel
Save