diff --git a/src/bin/rustii/info.rs b/src/bin/rustii/info.rs index 2672320..449b30f 100644 --- a/src/bin/rustii/info.rs +++ b/src/bin/rustii/info.rs @@ -102,12 +102,16 @@ fn print_wad_info(wad: wad::WAD) { wad::WADType::ImportBoot => { println!(" WAD Type: boot2") }, wad::WADType::Installable => { println!(" WAD Type: Standard Installable") }, } - println!(" Installed Size: WIP blocks"); - println!(" Installed Size (MB): WIP MB"); + // Create a Title for size info, signing info and TMD/Ticket info. + let title = title::Title::from_wad(&wad).unwrap(); + let min_size_blocks = title.title_size_blocks(None).unwrap(); + let max_size_blocks = title.title_size_blocks(Some(true)).unwrap(); + println!(" Installed Size: {}-{} blocks", min_size_blocks, max_size_blocks); + let min_size = title.title_size(None).unwrap() as f64 / 1048576.0; + let max_size = title.title_size(Some(true)).unwrap() as f64 / 1048576.0; + println!(" Installed Size (MB): {:.2}-{:.2} MB", min_size, max_size); println!(" Has Meta/Footer: {}", wad.meta_size() != 0); println!(" Has CRL: {}", wad.crl_size() != 0); - // Create a Title for signing info and TMD/Ticket info. - let title = title::Title::from_wad(&wad).unwrap(); println!(" Fakesigned: {}", title.is_fakesigned()); println!(); print_ticket_info(title.ticket); diff --git a/src/title/mod.rs b/src/title/mod.rs index 00e446a..0842637 100644 --- a/src/title/mod.rs +++ b/src/title/mod.rs @@ -110,6 +110,34 @@ impl Title { Ok(content) } + /// Gets the installed size of the title, in bytes. Use the optional parameter "absolute" to set + /// whether shared content should be included in this total or not. + pub fn title_size(&self, absolute: Option) -> Result { + let mut title_size: usize = 0; + // Get the TMD and Ticket size by dumping them and measuring their length for the most + // accurate results. + title_size += self.tmd.to_bytes().map_err(|x| TitleError::TMDError(tmd::TMDError::IOError(x)))?.len(); + title_size += self.ticket.to_bytes().map_err(|x| TitleError::TicketError(ticket::TicketError::IOError(x)))?.len(); + for record in &self.tmd.content_records { + if matches!(record.content_type, tmd::ContentType::Shared) { + if absolute == Some(true) { + title_size += record.content_size as usize; + } + } + else { + title_size += record.content_size as usize; + } + } + Ok(title_size) + } + + /// Gets the installed size of the title, in blocks. Use the optional parameter "absolute" to + /// set whether shared content should be included in this total or not. + pub fn title_size_blocks(&self, absolute: Option) -> Result { + let title_size_bytes = self.title_size(absolute)?; + Ok((title_size_bytes as f64 / 131072.0).ceil() as usize) + } + pub fn cert_chain(&self) -> Vec { self.cert_chain.clone() } diff --git a/src/title/tmd.rs b/src/title/tmd.rs index a72195a..20c0378 100644 --- a/src/title/tmd.rs +++ b/src/title/tmd.rs @@ -289,7 +289,7 @@ impl TMD { } Ok(()) } - + pub fn region(&self) -> &str { match self.region { 0 => "JPN", @@ -300,7 +300,7 @@ impl TMD { _ => "Unknown", } } - + pub fn title_type(&self) -> TitleType { match hex::encode(self.title_id)[..8].to_string().as_str() { "00000001" => TitleType::System, @@ -313,7 +313,7 @@ impl TMD { _ => TitleType::Unknown, } } - + pub fn content_type(&self, index: usize) -> ContentType { // Find possible content indices, because the provided one could exist while the indices // are out of order, which could cause problems finding the content. @@ -329,8 +329,8 @@ impl TMD { ContentType::DLC => ContentType::DLC, ContentType::Shared => ContentType::Shared, } - } - + } + pub fn check_access_right(&self, right: AccessRight) -> bool { match right { AccessRight::AHB => (self.access_rights & (1 << 0)) != 0,