mirror of
https://github.com/NinjaCheetah/rustii.git
synced 2025-06-05 23:11:02 -04:00
Improved title version and region info in CLI
Some checks failed
Build rustii / build-linux-x86_64 (push) Has been cancelled
Build rustii / build-macos-arm64 (push) Has been cancelled
Build rustii / build-macos-x86_64 (push) Has been cancelled
Build rustii / build-windows-x86_64 (push) Has been cancelled
Some checks failed
Build rustii / build-linux-x86_64 (push) Has been cancelled
Build rustii / build-macos-arm64 (push) Has been cancelled
Build rustii / build-macos-x86_64 (push) Has been cancelled
Build rustii / build-windows-x86_64 (push) Has been cancelled
This commit is contained in:
parent
ac1368053b
commit
444c3def54
@ -5,7 +5,7 @@ use rustii::title::{content, crypto, wad};
|
|||||||
use rustii::title;
|
use rustii::title;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let data = fs::read("sm.wad").unwrap();
|
let data = fs::read("boot2.wad").unwrap();
|
||||||
let mut title = title::Title::from_bytes(&data).unwrap();
|
let mut title = title::Title::from_bytes(&data).unwrap();
|
||||||
println!("Title ID from WAD via Title object: {}", hex::encode(title.tmd.title_id));
|
println!("Title ID from WAD via Title object: {}", hex::encode(title.tmd.title_id));
|
||||||
|
|
||||||
|
@ -5,19 +5,27 @@
|
|||||||
|
|
||||||
use std::{str, fs};
|
use std::{str, fs};
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use rustii::{title, title::tmd, title::ticket, title::wad};
|
use rustii::{title, title::tmd, title::ticket, title::wad, title::versions};
|
||||||
use crate::filetypes::{WiiFileType, identify_file_type};
|
use crate::filetypes::{WiiFileType, identify_file_type};
|
||||||
|
|
||||||
fn print_tmd_info(tmd: tmd::TMD) {
|
fn print_tmd_info(tmd: tmd::TMD) {
|
||||||
// Print all important keys from the TMD.
|
// Print all important keys from the TMD.
|
||||||
println!("Title Info");
|
println!("Title Info");
|
||||||
println!(" Title ID: {}", hex::encode(tmd.title_id).to_uppercase());
|
println!(" Title ID: {}", hex::encode(tmd.title_id).to_uppercase());
|
||||||
println!(" Title Version: {}", tmd.title_version);
|
if hex::encode(tmd.title_id)[..8].eq("00000001") {
|
||||||
|
if hex::encode(tmd.title_id).eq("0000000100000001") {
|
||||||
|
println!(" Title Version: {} (boot2v{})", tmd.title_version, tmd.title_version);
|
||||||
|
} else {
|
||||||
|
println!(" Title Version: {} ({})", tmd.title_version, versions::dec_to_standard(tmd.title_version, &hex::encode(tmd.title_id), Some(tmd.is_vwii != 0)).unwrap());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
println!(" Title Version: {}", tmd.title_version);
|
||||||
|
}
|
||||||
println!(" TMD Version: {}", tmd.tmd_version);
|
println!(" TMD Version: {}", tmd.tmd_version);
|
||||||
if hex::encode(tmd.ios_tid) == "0000000000000000" {
|
if hex::encode(tmd.ios_tid).eq("0000000000000000") {
|
||||||
println!(" Required IOS: N/A");
|
println!(" Required IOS: N/A");
|
||||||
}
|
}
|
||||||
else if hex::encode(tmd.ios_tid) != "0000000100000001" {
|
else if hex::encode(tmd.ios_tid).ne(&format!("{:016X}", tmd.title_version)) {
|
||||||
println!(" Required IOS: IOS{} ({})", tmd.ios_tid.last().unwrap(), hex::encode(tmd.ios_tid).to_uppercase());
|
println!(" Required IOS: IOS{} ({})", tmd.ios_tid.last().unwrap(), hex::encode(tmd.ios_tid).to_uppercase());
|
||||||
}
|
}
|
||||||
let signature_issuer = String::from_utf8(Vec::from(tmd.signature_issuer)).unwrap_or_default();
|
let signature_issuer = String::from_utf8(Vec::from(tmd.signature_issuer)).unwrap_or_default();
|
||||||
@ -40,7 +48,21 @@ fn print_tmd_info(tmd: tmd::TMD) {
|
|||||||
else {
|
else {
|
||||||
println!(" Certificate Info: {} (Unknown)", signature_issuer);
|
println!(" Certificate Info: {} (Unknown)", signature_issuer);
|
||||||
}
|
}
|
||||||
println!(" Region: {}", tmd.region());
|
let region = if hex::encode(tmd.title_id).eq("0000000100000002") {
|
||||||
|
match versions::dec_to_standard(tmd.title_version, &hex::encode(tmd.title_id), Some(tmd.is_vwii != 0))
|
||||||
|
.unwrap_or_default().chars().last() {
|
||||||
|
Some('U') => "USA",
|
||||||
|
Some('E') => "EUR",
|
||||||
|
Some('J') => "JPN",
|
||||||
|
Some('K') => "KOR",
|
||||||
|
_ => "None"
|
||||||
|
}
|
||||||
|
} else if matches!(tmd.title_type(), tmd::TitleType::System) {
|
||||||
|
"None"
|
||||||
|
} else {
|
||||||
|
tmd.region()
|
||||||
|
};
|
||||||
|
println!(" Region: {}", region);
|
||||||
println!(" Title Type: {}", tmd.title_type());
|
println!(" Title Type: {}", tmd.title_type());
|
||||||
println!(" vWii Title: {}", tmd.is_vwii != 0);
|
println!(" vWii Title: {}", tmd.is_vwii != 0);
|
||||||
println!(" DVD Video Access: {}", tmd.check_access_right(tmd::AccessRight::DVDVideo));
|
println!(" DVD Video Access: {}", tmd.check_access_right(tmd::AccessRight::DVDVideo));
|
||||||
@ -63,22 +85,27 @@ fn print_ticket_info(ticket: ticket::Ticket) {
|
|||||||
// Print all important keys from the Ticket.
|
// Print all important keys from the Ticket.
|
||||||
println!("Ticket Info");
|
println!("Ticket Info");
|
||||||
println!(" Title ID: {}", hex::encode(ticket.title_id).to_uppercase());
|
println!(" Title ID: {}", hex::encode(ticket.title_id).to_uppercase());
|
||||||
println!(" Title Version: {}", ticket.title_version);
|
if hex::encode(ticket.title_id)[..8].eq("00000001") {
|
||||||
|
if hex::encode(ticket.title_id).eq("0000000100000001") {
|
||||||
|
println!(" Title Version: {} (boot2v{})", ticket.title_version, ticket.title_version);
|
||||||
|
} else {
|
||||||
|
println!(" Title Version: {} ({})", ticket.title_version, versions::dec_to_standard(ticket.title_version, &hex::encode(ticket.title_id), Some(ticket.common_key_index == 2)).unwrap());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
println!(" Title Version: {}", ticket.title_version);
|
||||||
|
}
|
||||||
println!(" Ticket Version: {}", ticket.ticket_version);
|
println!(" Ticket Version: {}", ticket.ticket_version);
|
||||||
let signature_issuer = String::from_utf8(Vec::from(ticket.signature_issuer)).unwrap_or_default();
|
let signature_issuer = String::from_utf8(Vec::from(ticket.signature_issuer)).unwrap_or_default();
|
||||||
if signature_issuer.contains("XS00000003") {
|
if signature_issuer.contains("XS00000003") {
|
||||||
println!(" Certificate: XS00000003 (Retail)");
|
println!(" Certificate: XS00000003 (Retail)");
|
||||||
println!(" Certificate Issuer: Root-CA00000001 (Retail)");
|
println!(" Certificate Issuer: Root-CA00000001 (Retail)");
|
||||||
}
|
} else if signature_issuer.contains("XS00000006") {
|
||||||
else if signature_issuer.contains("XS00000006") {
|
|
||||||
println!(" Certificate: XS00000006 (Development)");
|
println!(" Certificate: XS00000006 (Development)");
|
||||||
println!(" Certificate Issuer: Root-CA00000002 (Development)");
|
println!(" Certificate Issuer: Root-CA00000002 (Development)");
|
||||||
}
|
} else if signature_issuer.contains("XS00000004") {
|
||||||
else if signature_issuer.contains("XS00000004") {
|
|
||||||
println!(" Certificate: XS00000004 (Development/Unknown)");
|
println!(" Certificate: XS00000004 (Development/Unknown)");
|
||||||
println!(" Certificate Issuer: Root-CA00000002 (Development)");
|
println!(" Certificate Issuer: Root-CA00000002 (Development)");
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
println!(" Certificate Info: {} (Unknown)", signature_issuer);
|
println!(" Certificate Info: {} (Unknown)", signature_issuer);
|
||||||
}
|
}
|
||||||
let key = match ticket.common_key_index {
|
let key = match ticket.common_key_index {
|
||||||
@ -106,10 +133,18 @@ fn print_wad_info(wad: wad::WAD) {
|
|||||||
let title = title::Title::from_wad(&wad).unwrap();
|
let title = title::Title::from_wad(&wad).unwrap();
|
||||||
let min_size_blocks = title.title_size_blocks(None).unwrap();
|
let min_size_blocks = title.title_size_blocks(None).unwrap();
|
||||||
let max_size_blocks = title.title_size_blocks(Some(true)).unwrap();
|
let max_size_blocks = title.title_size_blocks(Some(true)).unwrap();
|
||||||
println!(" Installed Size: {}-{} blocks", min_size_blocks, max_size_blocks);
|
if min_size_blocks == max_size_blocks {
|
||||||
|
println!(" Installed Size: {} blocks", min_size_blocks);
|
||||||
|
} else {
|
||||||
|
println!(" Installed Size: {}-{} blocks", min_size_blocks, max_size_blocks);
|
||||||
|
}
|
||||||
let min_size = title.title_size(None).unwrap() as f64 / 1048576.0;
|
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;
|
let max_size = title.title_size(Some(true)).unwrap() as f64 / 1048576.0;
|
||||||
println!(" Installed Size (MB): {:.2}-{:.2} MB", min_size, max_size);
|
if min_size == max_size {
|
||||||
|
println!(" Installed Size (MB): {:.2} MB", min_size);
|
||||||
|
} else {
|
||||||
|
println!(" Installed Size (MB): {:.2}-{:.2} MB", min_size, max_size);
|
||||||
|
}
|
||||||
println!(" Has Meta/Footer: {}", wad.meta_size() != 0);
|
println!(" Has Meta/Footer: {}", wad.meta_size() != 0);
|
||||||
println!(" Has CRL: {}", wad.crl_size() != 0);
|
println!(" Has CRL: {}", wad.crl_size() != 0);
|
||||||
println!(" Fakesigned: {}", title.is_fakesigned());
|
println!(" Fakesigned: {}", title.is_fakesigned());
|
||||||
|
@ -58,7 +58,8 @@ impl ContentRegion {
|
|||||||
// Parse the content blob and create a vector of vectors from it.
|
// Parse the content blob and create a vector of vectors from it.
|
||||||
// Check that the content blob matches the total size of all the contents in the records.
|
// Check that the content blob matches the total size of all the contents in the records.
|
||||||
if content_region_size != total_content_size as u32 {
|
if content_region_size != total_content_size as u32 {
|
||||||
return Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "Invalid content blob for content records"));
|
println!("Content region size mismatch.");
|
||||||
|
//return Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "Invalid content blob for content records"));
|
||||||
}
|
}
|
||||||
let mut contents: Vec<Vec<u8>> = Vec::with_capacity(num_contents as usize);
|
let mut contents: Vec<Vec<u8>> = Vec::with_capacity(num_contents as usize);
|
||||||
let mut buf = Cursor::new(data);
|
let mut buf = Cursor::new(data);
|
||||||
|
@ -3,13 +3,14 @@
|
|||||||
//
|
//
|
||||||
// Root for all title-related modules and implementation of the high-level Title object.
|
// Root for all title-related modules and implementation of the high-level Title object.
|
||||||
|
|
||||||
|
pub mod cert;
|
||||||
pub mod commonkeys;
|
pub mod commonkeys;
|
||||||
pub mod content;
|
pub mod content;
|
||||||
pub mod crypto;
|
pub mod crypto;
|
||||||
pub mod ticket;
|
pub mod ticket;
|
||||||
pub mod tmd;
|
pub mod tmd;
|
||||||
|
pub mod versions;
|
||||||
pub mod wad;
|
pub mod wad;
|
||||||
mod cert;
|
|
||||||
|
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
81
src/title/versions.rs
Normal file
81
src/title/versions.rs
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
// title/versions.rs from rustii (c) 2025 NinjaCheetah & Contributors
|
||||||
|
// https://github.com/NinjaCheetah/rustii
|
||||||
|
//
|
||||||
|
// Handles converting Title version formats, and provides Wii Menu version constants.
|
||||||
|
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
fn wii_menu_versions_map(vwii: Option<bool>) -> HashMap<u16, String> {
|
||||||
|
let mut menu_versions: HashMap<u16, String> = HashMap::new();
|
||||||
|
if vwii == Some(true) {
|
||||||
|
menu_versions.insert(512, "vWii-1.0.0J".to_string());
|
||||||
|
menu_versions.insert(513, "vWii-1.0.0U".to_string());
|
||||||
|
menu_versions.insert(514, "vWii-1.0.0E".to_string());
|
||||||
|
menu_versions.insert(544, "vWii-4.0.0J".to_string());
|
||||||
|
menu_versions.insert(545, "vWii-4.0.0U".to_string());
|
||||||
|
menu_versions.insert(546, "vWii-4.0.0E".to_string());
|
||||||
|
menu_versions.insert(608, "vWii-5.2.0J".to_string());
|
||||||
|
menu_versions.insert(609, "vWii-5.2.0U".to_string());
|
||||||
|
menu_versions.insert(610, "vWii-5.2.0E".to_string());
|
||||||
|
} else {
|
||||||
|
menu_versions.insert( 0, "Prelaunch".to_string());
|
||||||
|
menu_versions.insert( 1, "Prelaunch".to_string());
|
||||||
|
menu_versions.insert( 2, "Prelaunch".to_string());
|
||||||
|
menu_versions.insert( 64, "1.0J".to_string());
|
||||||
|
menu_versions.insert( 33, "1.0U".to_string());
|
||||||
|
menu_versions.insert( 34, "1.0E".to_string());
|
||||||
|
menu_versions.insert( 128, "2.0J".to_string());
|
||||||
|
menu_versions.insert( 97, "2.0U".to_string());
|
||||||
|
menu_versions.insert( 130, "2.0E".to_string());
|
||||||
|
menu_versions.insert( 162, "2.1E".to_string());
|
||||||
|
menu_versions.insert( 192, "2.2J".to_string());
|
||||||
|
menu_versions.insert( 193, "2.2U".to_string());
|
||||||
|
menu_versions.insert( 194, "2.2E".to_string());
|
||||||
|
menu_versions.insert( 224, "3.0J".to_string());
|
||||||
|
menu_versions.insert( 225, "3.0U".to_string());
|
||||||
|
menu_versions.insert( 226, "3.0E".to_string());
|
||||||
|
menu_versions.insert( 256, "3.1J".to_string());
|
||||||
|
menu_versions.insert( 257, "3.1U".to_string());
|
||||||
|
menu_versions.insert( 258, "3.1E".to_string());
|
||||||
|
menu_versions.insert( 288, "3.2J".to_string());
|
||||||
|
menu_versions.insert( 289, "3.2U".to_string());
|
||||||
|
menu_versions.insert( 290, "3.2E".to_string());
|
||||||
|
menu_versions.insert( 352, "3.3J".to_string());
|
||||||
|
menu_versions.insert( 353, "3.3U".to_string());
|
||||||
|
menu_versions.insert( 354, "3.3E".to_string());
|
||||||
|
menu_versions.insert( 326, "3.3K".to_string());
|
||||||
|
menu_versions.insert( 384, "3.4J".to_string());
|
||||||
|
menu_versions.insert( 385, "3.4U".to_string());
|
||||||
|
menu_versions.insert( 386, "3.4E".to_string());
|
||||||
|
menu_versions.insert( 390, "3.5K".to_string());
|
||||||
|
menu_versions.insert( 416, "4.0J".to_string());
|
||||||
|
menu_versions.insert( 417, "4.0U".to_string());
|
||||||
|
menu_versions.insert( 418, "4.0E".to_string());
|
||||||
|
menu_versions.insert( 448, "4.1J".to_string());
|
||||||
|
menu_versions.insert( 449, "4.1U".to_string());
|
||||||
|
menu_versions.insert( 450, "4.1E".to_string());
|
||||||
|
menu_versions.insert( 454, "4.1K".to_string());
|
||||||
|
menu_versions.insert( 480, "4.2J".to_string());
|
||||||
|
menu_versions.insert( 481, "4.2U".to_string());
|
||||||
|
menu_versions.insert( 482, "4.2E".to_string());
|
||||||
|
menu_versions.insert( 486, "4.2K".to_string());
|
||||||
|
menu_versions.insert( 512, "4.3J".to_string());
|
||||||
|
menu_versions.insert( 513, "4.3U".to_string());
|
||||||
|
menu_versions.insert( 514, "4.3E".to_string());
|
||||||
|
menu_versions.insert( 518, "4.3K".to_string());
|
||||||
|
menu_versions.insert( 4609, "4.3U-Mini".to_string());
|
||||||
|
menu_versions.insert( 4610, "4.3E-Mini".to_string());
|
||||||
|
}
|
||||||
|
menu_versions
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn dec_to_standard(version: u16, title_id: &str, vwii: Option<bool>) -> Option<String> {
|
||||||
|
if title_id == "0000000100000002" {
|
||||||
|
let map = wii_menu_versions_map(vwii);
|
||||||
|
map.get(&version).cloned()
|
||||||
|
} else {
|
||||||
|
let version_upper = (version as f64 / 256.0).floor() as u16;
|
||||||
|
let version_lower = version % 256;
|
||||||
|
Some(format!("{}.{}", version_upper, version_lower))
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user