mirror of
https://github.com/NinjaCheetah/rustii.git
synced 2025-06-06 15:31: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)
|
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.
|
// Common code for identifying Wii file types.
|
||||||
|
|
||||||
use std::{str, fs::File};
|
use std::{str, fs::File};
|
||||||
use std::io::Read;
|
use std::io::{Read, Seek, SeekFrom};
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use regex::RegexBuilder;
|
use regex::RegexBuilder;
|
||||||
|
|
||||||
@ -13,7 +13,8 @@ use regex::RegexBuilder;
|
|||||||
pub enum WiiFileType {
|
pub enum WiiFileType {
|
||||||
Wad,
|
Wad,
|
||||||
Tmd,
|
Tmd,
|
||||||
Ticket
|
Ticket,
|
||||||
|
U8,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn identify_file_type(input: &str) -> Option<WiiFileType> {
|
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")) {
|
if input.extension().is_some_and(|f| f.eq_ignore_ascii_case("wad")) {
|
||||||
return Some(WiiFileType::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() {
|
if input.exists() {
|
||||||
let mut f = File::open(input).unwrap();
|
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];
|
let mut magic_number = vec![0u8; 8];
|
||||||
f.read_exact(&mut magic_number).unwrap();
|
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" {
|
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);
|
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! ==
|
// == No match found! ==
|
||||||
|
@ -4,8 +4,11 @@
|
|||||||
// Code for the info command in the rustii CLI.
|
// Code for the info command in the rustii CLI.
|
||||||
|
|
||||||
use std::{str, fs};
|
use std::{str, fs};
|
||||||
|
use std::cell::RefCell;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
use std::rc::Rc;
|
||||||
use anyhow::{bail, Context, Result};
|
use anyhow::{bail, Context, Result};
|
||||||
|
use rustii::archive::u8;
|
||||||
use rustii::{title, title::cert, title::tmd, title::ticket, title::wad, title::versions};
|
use rustii::{title, title::cert, title::tmd, title::ticket, title::wad, title::versions};
|
||||||
use crate::filetypes::{WiiFileType, identify_file_type};
|
use crate::filetypes::{WiiFileType, identify_file_type};
|
||||||
|
|
||||||
@ -240,6 +243,35 @@ fn print_wad_info(wad: wad::WAD) -> Result<()> {
|
|||||||
Ok(())
|
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<()> {
|
pub fn info(input: &str) -> Result<()> {
|
||||||
let in_path = Path::new(input);
|
let in_path = Path::new(input);
|
||||||
if !in_path.exists() {
|
if !in_path.exists() {
|
||||||
@ -247,17 +279,21 @@ pub fn info(input: &str) -> Result<()> {
|
|||||||
}
|
}
|
||||||
match identify_file_type(input) {
|
match identify_file_type(input) {
|
||||||
Some(WiiFileType::Tmd) => {
|
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)?;
|
print_tmd_info(tmd, None)?;
|
||||||
},
|
},
|
||||||
Some(WiiFileType::Ticket) => {
|
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)?;
|
print_ticket_info(ticket, None)?;
|
||||||
},
|
},
|
||||||
Some(WiiFileType::Wad) => {
|
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)?;
|
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 => {
|
None => {
|
||||||
bail!("Information cannot be displayed for this file type.");
|
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.")?;
|
fs::write(out_path, ticket.to_bytes()?).with_context(|| "Could not open output file for writing.")?;
|
||||||
println!("Ticket fakesigned!");
|
println!("Ticket fakesigned!");
|
||||||
},
|
},
|
||||||
None => {
|
_ => {
|
||||||
bail!("You can only fakesign TMDs, Tickets, and WADs!");
|
bail!("You can only fakesign TMDs, Tickets, and WADs!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user