Extract Wii region.bin

This commit is contained in:
Luke Street 2024-10-04 19:53:07 -06:00
parent d99ef72fe9
commit f4638369d1
6 changed files with 44 additions and 21 deletions

12
Cargo.lock generated
View File

@ -441,7 +441,7 @@ dependencies = [
[[package]] [[package]]
name = "nod" name = "nod"
version = "1.4.1" version = "1.4.2"
dependencies = [ dependencies = [
"adler", "adler",
"aes", "aes",
@ -464,7 +464,7 @@ dependencies = [
[[package]] [[package]]
name = "nodtool" name = "nodtool"
version = "1.4.1" version = "1.4.2"
dependencies = [ dependencies = [
"argp", "argp",
"base16ct", "base16ct",
@ -1033,18 +1033,18 @@ checksum = "6a5cbf750400958819fb6178eaa83bee5cd9c29a26a40cc241df8c70fdd46984"
[[package]] [[package]]
name = "zerocopy" name = "zerocopy"
version = "0.8.0" version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df7885ffcb82507a0f213c593e77c5f13d12cb96588d4e835ad7e9423ba034db" checksum = "dd2e5ce961dea177d282ec084dca2aa411b7411199a68d79eb1beacb305a6cd9"
dependencies = [ dependencies = [
"zerocopy-derive", "zerocopy-derive",
] ]
[[package]] [[package]]
name = "zerocopy-derive" name = "zerocopy-derive"
version = "0.8.0" version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "930ad75608219e8ffdb8962a5433cb2b30064c7ccb564d3b76c2963390b1e435" checksum = "b06304eeddb6081af98ac59db08c868ac197e586086b996d15a86ed70e09a754"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",

View File

@ -9,7 +9,7 @@ strip = "debuginfo"
codegen-units = 1 codegen-units = 1
[workspace.package] [workspace.package]
version = "1.4.1" version = "1.4.2"
edition = "2021" edition = "2021"
rust-version = "1.74" rust-version = "1.74"
authors = ["Luke Street <luke@street.dev>"] authors = ["Luke Street <luke@street.dev>"]

View File

@ -214,6 +214,7 @@ pub(crate) fn read_part_meta(
raw_apploader: raw_apploader.into_boxed_slice(), raw_apploader: raw_apploader.into_boxed_slice(),
raw_fst, raw_fst,
raw_dol: raw_dol.into_boxed_slice(), raw_dol: raw_dol.into_boxed_slice(),
raw_region: None,
raw_ticket: None, raw_ticket: None,
raw_tmd: None, raw_tmd: None,
raw_cert_chain: None, raw_cert_chain: None,

View File

@ -24,7 +24,7 @@ pub(crate) mod wii;
pub use fst::{Fst, Node, NodeKind}; pub use fst::{Fst, Node, NodeKind};
pub use streams::{FileStream, OwnedFileStream, WindowedStream}; pub use streams::{FileStream, OwnedFileStream, WindowedStream};
pub use wii::{SignedHeader, Ticket, TicketLimit, TmdHeader}; pub use wii::{SignedHeader, Ticket, TicketLimit, TmdHeader, REGION_SIZE};
/// Size in bytes of a disc sector. /// Size in bytes of a disc sector.
pub const SECTOR_SIZE: usize = 0x8000; pub const SECTOR_SIZE: usize = 0x8000;
@ -365,6 +365,8 @@ pub struct PartitionMeta {
pub raw_fst: Box<[u8]>, pub raw_fst: Box<[u8]>,
/// Main binary (main.dol) /// Main binary (main.dol)
pub raw_dol: Box<[u8]>, pub raw_dol: Box<[u8]>,
/// Disc region info (region.bin, Wii only)
pub raw_region: Option<Box<[u8; REGION_SIZE]>>,
/// Ticket (ticket.bin, Wii only) /// Ticket (ticket.bin, Wii only)
pub raw_ticket: Option<Box<[u8]>>, pub raw_ticket: Option<Box<[u8]>>,
/// TMD (tmd.bin, Wii only) /// TMD (tmd.bin, Wii only)

View File

@ -21,7 +21,10 @@ use crate::{
KeyBytes, KeyBytes,
}, },
static_assert, static_assert,
util::{div_rem, read::read_box_slice}, util::{
div_rem,
read::{read_box, read_box_slice},
},
Error, OpenOptions, Result, ResultContext, Error, OpenOptions, Result, ResultContext,
}; };
@ -31,6 +34,12 @@ pub(crate) const HASHES_SIZE: usize = 0x400;
/// Size in bytes of the data block in a Wii disc sector (excluding hashes) /// Size in bytes of the data block in a Wii disc sector (excluding hashes)
pub(crate) const SECTOR_DATA_SIZE: usize = SECTOR_SIZE - HASHES_SIZE; // 0x7C00 pub(crate) const SECTOR_DATA_SIZE: usize = SECTOR_SIZE - HASHES_SIZE; // 0x7C00
/// Size of the disc region info (region.bin)
pub const REGION_SIZE: usize = 0x20;
/// Offset of the disc region info
pub const REGION_OFFSET: u64 = 0x4E000;
// ppki (Retail) // ppki (Retail)
const RVL_CERT_ISSUER_PPKI_TICKET: &str = "Root-CA00000001-XS00000003"; const RVL_CERT_ISSUER_PPKI_TICKET: &str = "Root-CA00000001-XS00000003";
#[rustfmt::skip] #[rustfmt::skip]
@ -270,6 +279,7 @@ pub struct PartitionWii {
sector: u32, sector: u32,
pos: u64, pos: u64,
verify: bool, verify: bool,
raw_region: Box<[u8; REGION_SIZE]>,
raw_tmd: Box<[u8]>, raw_tmd: Box<[u8]>,
raw_cert_chain: Box<[u8]>, raw_cert_chain: Box<[u8]>,
raw_h3_table: Box<[u8]>, raw_h3_table: Box<[u8]>,
@ -287,6 +297,7 @@ impl Clone for PartitionWii {
sector: u32::MAX, sector: u32::MAX,
pos: 0, pos: 0,
verify: self.verify, verify: self.verify,
raw_region: self.raw_region.clone(),
raw_tmd: self.raw_tmd.clone(), raw_tmd: self.raw_tmd.clone(),
raw_cert_chain: self.raw_cert_chain.clone(), raw_cert_chain: self.raw_cert_chain.clone(),
raw_h3_table: self.raw_h3_table.clone(), raw_h3_table: self.raw_h3_table.clone(),
@ -304,6 +315,10 @@ impl PartitionWii {
let block_size = inner.block_size(); let block_size = inner.block_size();
let mut reader = PartitionGC::new(inner, disc_header)?; let mut reader = PartitionGC::new(inner, disc_header)?;
// Read region
reader.seek(SeekFrom::Start(REGION_OFFSET)).context("Seeking to region offset")?;
let raw_region: Box<[u8; REGION_SIZE]> = read_box(&mut reader).context("Reading region")?;
// Read TMD, cert chain, and H3 table // Read TMD, cert chain, and H3 table
let offset = partition.start_sector as u64 * SECTOR_SIZE as u64; let offset = partition.start_sector as u64 * SECTOR_SIZE as u64;
reader reader
@ -333,6 +348,7 @@ impl PartitionWii {
sector: u32::MAX, sector: u32::MAX,
pos: 0, pos: 0,
verify: options.validate_hashes, verify: options.validate_hashes,
raw_region,
raw_tmd, raw_tmd,
raw_cert_chain, raw_cert_chain,
raw_h3_table, raw_h3_table,
@ -482,6 +498,7 @@ impl PartitionBase for PartitionWii {
fn meta(&mut self) -> Result<Box<PartitionMeta>> { fn meta(&mut self) -> Result<Box<PartitionMeta>> {
self.seek(SeekFrom::Start(0)).context("Seeking to partition header")?; self.seek(SeekFrom::Start(0)).context("Seeking to partition header")?;
let mut meta = read_part_meta(self, true)?; let mut meta = read_part_meta(self, true)?;
meta.raw_region = Some(self.raw_region.clone());
meta.raw_ticket = Some(Box::from(self.partition.header.ticket.as_bytes())); meta.raw_ticket = Some(Box::from(self.partition.header.ticket.as_bytes()));
meta.raw_tmd = Some(self.raw_tmd.clone()); meta.raw_tmd = Some(self.raw_tmd.clone());
meta.raw_cert_chain = Some(self.raw_cert_chain.clone()); meta.raw_cert_chain = Some(self.raw_cert_chain.clone());

View File

@ -152,6 +152,8 @@ fn extract_sys_files(
fs::create_dir_all(&disc_dir) fs::create_dir_all(&disc_dir)
.with_context(|| format!("Creating directory {}", display(&disc_dir)))?; .with_context(|| format!("Creating directory {}", display(&disc_dir)))?;
extract_file(&header.as_bytes()[..0x100], &disc_dir.join("header.bin"), quiet)?; extract_file(&header.as_bytes()[..0x100], &disc_dir.join("header.bin"), quiet)?;
if let Some(region) = data.raw_region.as_deref() {
extract_file(region, &disc_dir.join("region.bin"), quiet)?;
} }
if let Some(ticket) = data.raw_ticket.as_deref() { if let Some(ticket) = data.raw_ticket.as_deref() {
extract_file(ticket, &out_dir.join("ticket.bin"), quiet)?; extract_file(ticket, &out_dir.join("ticket.bin"), quiet)?;
@ -165,6 +167,7 @@ fn extract_sys_files(
if let Some(h3_table) = data.raw_h3_table.as_deref() { if let Some(h3_table) = data.raw_h3_table.as_deref() {
extract_file(h3_table, &out_dir.join("h3.bin"), quiet)?; extract_file(h3_table, &out_dir.join("h3.bin"), quiet)?;
} }
}
Ok(()) Ok(())
} }