mirror of
https://github.com/NinjaCheetah/rustii.git
synced 2025-06-05 23:11:02 -04:00
Added basic support for displaying info about U8 archives to rustii CLI
This commit is contained in:
parent
ea2e31756c
commit
66476e2c98
@ -345,19 +345,3 @@ impl U8Archive {
|
||||
Ok(buf)
|
||||
}
|
||||
}
|
||||
|
||||
// pub fn print_full_tree(dir: &Rc<RefCell<U8Directory>>, indent: usize) {
|
||||
// let prefix = " ".repeat(indent);
|
||||
// println!("{}D {}", prefix, dir.borrow().name);
|
||||
//
|
||||
// // Print subdirectories
|
||||
// for subdir in &dir.borrow().dirs {
|
||||
// print_full_tree(subdir, indent + 1);
|
||||
// }
|
||||
//
|
||||
// // Print files
|
||||
// for file in &dir.borrow().files {
|
||||
// let file_name = &file.borrow().name;
|
||||
// println!("{} F {}", prefix, file_name);
|
||||
// }
|
||||
// }
|
||||
|
@ -4,7 +4,7 @@
|
||||
// Common code for identifying Wii file types.
|
||||
|
||||
use std::{str, fs::File};
|
||||
use std::io::Read;
|
||||
use std::io::{Read, Seek, SeekFrom};
|
||||
use std::path::Path;
|
||||
use regex::RegexBuilder;
|
||||
|
||||
@ -13,7 +13,8 @@ use regex::RegexBuilder;
|
||||
pub enum WiiFileType {
|
||||
Wad,
|
||||
Tmd,
|
||||
Ticket
|
||||
Ticket,
|
||||
U8,
|
||||
}
|
||||
|
||||
pub fn identify_file_type(input: &str) -> Option<WiiFileType> {
|
||||
@ -35,14 +36,30 @@ pub fn identify_file_type(input: &str) -> Option<WiiFileType> {
|
||||
if input.extension().is_some_and(|f| f.eq_ignore_ascii_case("wad")) {
|
||||
return Some(WiiFileType::Wad);
|
||||
}
|
||||
// Advanced WAD detection, where we read and compare the first 8 bytes (only if the path exists.)
|
||||
// == U8 ==
|
||||
if input.extension().is_some_and(|f| f.eq_ignore_ascii_case("arc")) ||
|
||||
input.extension().is_some_and(|f| f.eq_ignore_ascii_case("app")) {
|
||||
return Some(WiiFileType::U8);
|
||||
}
|
||||
|
||||
// == Advanced ==
|
||||
// These require reading the magic number of the file, so we only try this after everything
|
||||
// else has been tried. These are separated from the other methods of detecting these types so
|
||||
// that we only have to open the file for reading once.
|
||||
if input.exists() {
|
||||
let mut f = File::open(input).unwrap();
|
||||
// We need to read more bytes for WADs since they don't have a proper magic number.
|
||||
let mut magic_number = vec![0u8; 8];
|
||||
f.read_exact(&mut magic_number).unwrap();
|
||||
if magic_number == b"\x00\x00\x00\x20\x49\x73\x00\x00" || magic_number == b"\x00\x00\x00\x20\x69\x62\x00\x00" {
|
||||
return Some(WiiFileType::Wad);
|
||||
}
|
||||
let mut magic_number = vec![0u8; 4];
|
||||
f.seek(SeekFrom::Start(0)).unwrap();
|
||||
f.read_exact(&mut magic_number).unwrap();
|
||||
if magic_number == b"\x55\xAA\x38\x2D" {
|
||||
return Some(WiiFileType::U8);
|
||||
}
|
||||
}
|
||||
|
||||
// == No match found! ==
|
||||
|
@ -4,8 +4,11 @@
|
||||
// Code for the info command in the rustii CLI.
|
||||
|
||||
use std::{str, fs};
|
||||
use std::cell::RefCell;
|
||||
use std::path::Path;
|
||||
use std::rc::Rc;
|
||||
use anyhow::{bail, Context, Result};
|
||||
use rustii::archive::u8;
|
||||
use rustii::{title, title::cert, title::tmd, title::ticket, title::wad, title::versions};
|
||||
use crate::filetypes::{WiiFileType, identify_file_type};
|
||||
|
||||
@ -240,6 +243,35 @@ fn print_wad_info(wad: wad::WAD) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn print_full_tree(dir: &Rc<RefCell<u8::U8Directory>>, indent: usize) {
|
||||
let prefix = " ".repeat(indent);
|
||||
let dir_name = if !dir.borrow().name.is_empty() {
|
||||
&dir.borrow().name
|
||||
} else {
|
||||
&String::from("root")
|
||||
};
|
||||
println!("{}D {}", prefix, dir_name);
|
||||
|
||||
// Print subdirectories
|
||||
for subdir in &dir.borrow().dirs {
|
||||
print_full_tree(subdir, indent + 1);
|
||||
}
|
||||
|
||||
// Print files
|
||||
for file in &dir.borrow().files {
|
||||
let file_name = &file.borrow().name;
|
||||
println!("{} F {}", prefix, file_name);
|
||||
}
|
||||
}
|
||||
|
||||
fn print_u8_info(u8_archive: u8::U8Archive) -> Result<()> {
|
||||
println!("U8 Archive Info");
|
||||
println!(" Node Count: {}", u8_archive.node_tree.borrow().count());
|
||||
println!(" Archive Data:");
|
||||
print_full_tree(&u8_archive.node_tree, 2);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn info(input: &str) -> Result<()> {
|
||||
let in_path = Path::new(input);
|
||||
if !in_path.exists() {
|
||||
@ -247,17 +279,21 @@ pub fn info(input: &str) -> Result<()> {
|
||||
}
|
||||
match identify_file_type(input) {
|
||||
Some(WiiFileType::Tmd) => {
|
||||
let tmd = tmd::TMD::from_bytes(fs::read(in_path)?.as_slice()).with_context(|| "The provided TMD file could not be parsed, and is likely invalid.")?;
|
||||
let tmd = tmd::TMD::from_bytes(&fs::read(in_path)?).with_context(|| "The provided TMD file could not be parsed, and is likely invalid.")?;
|
||||
print_tmd_info(tmd, None)?;
|
||||
},
|
||||
Some(WiiFileType::Ticket) => {
|
||||
let ticket = ticket::Ticket::from_bytes(fs::read(in_path)?.as_slice()).with_context(|| "The provided Ticket file could not be parsed, and is likely invalid.")?;
|
||||
let ticket = ticket::Ticket::from_bytes(&fs::read(in_path)?).with_context(|| "The provided Ticket file could not be parsed, and is likely invalid.")?;
|
||||
print_ticket_info(ticket, None)?;
|
||||
},
|
||||
Some(WiiFileType::Wad) => {
|
||||
let wad = wad::WAD::from_bytes(fs::read(in_path)?.as_slice()).with_context(|| "The provided WAD file could not be parsed, and is likely invalid.")?;
|
||||
let wad = wad::WAD::from_bytes(&fs::read(in_path)?).with_context(|| "The provided WAD file could not be parsed, and is likely invalid.")?;
|
||||
print_wad_info(wad)?;
|
||||
},
|
||||
Some(WiiFileType::U8) => {
|
||||
let u8_archive = u8::U8Archive::from_bytes(&fs::read(in_path)?).with_context(|| "The provided U8 archive could not be parsed, and is likely invalid.")?;
|
||||
print_u8_info(u8_archive)?;
|
||||
}
|
||||
None => {
|
||||
bail!("Information cannot be displayed for this file type.");
|
||||
}
|
||||
|
@ -57,7 +57,7 @@ pub fn fakesign(input: &str, output: &Option<String>) -> Result<()> {
|
||||
fs::write(out_path, ticket.to_bytes()?).with_context(|| "Could not open output file for writing.")?;
|
||||
println!("Ticket fakesigned!");
|
||||
},
|
||||
None => {
|
||||
_ => {
|
||||
bail!("You can only fakesign TMDs, Tickets, and WADs!");
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user