Skip to content

Commit

Permalink
Add RVZ packing support
Browse files Browse the repository at this point in the history
  • Loading branch information
encounter committed Nov 30, 2024
1 parent 55b0d3f commit 1e44f23
Show file tree
Hide file tree
Showing 12 changed files with 897 additions and 366 deletions.
35 changes: 30 additions & 5 deletions nod/src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,12 @@
use std::{borrow::Cow, fmt, str::FromStr, sync::Arc};

use zerocopy::FromBytes;

use crate::{
disc::{wii::WiiPartitionHeader, DiscHeader, PartitionHeader, SECTOR_SIZE},
disc::{
fst::Fst, wii::WiiPartitionHeader, DiscHeader, PartitionHeader, BOOT_SIZE, SECTOR_SIZE,
},
Error, Result,
};

Expand Down Expand Up @@ -300,14 +304,14 @@ pub struct PartitionInfo {
pub key: KeyBytes,
/// The Wii partition header.
pub header: Arc<WiiPartitionHeader>,
/// The disc header within the partition.
pub disc_header: Arc<DiscHeader>,
/// The partition header within the partition.
pub partition_header: Arc<PartitionHeader>,
/// Whether the partition data is encrypted
pub has_encryption: bool,
/// Whether the partition data hashes are present
pub has_hashes: bool,
/// Disc and partition header (boot.bin)
pub raw_boot: Arc<[u8; BOOT_SIZE]>,
/// File system table (fst.bin), or `None` if partition is invalid
pub raw_fst: Option<Arc<[u8]>>,
}

impl PartitionInfo {
Expand All @@ -322,4 +326,25 @@ impl PartitionInfo {
pub fn data_contains_sector(&self, sector: u32) -> bool {
sector >= self.data_start_sector && sector < self.data_end_sector
}

/// A view into the disc header.
#[inline]
pub fn disc_header(&self) -> &DiscHeader {
DiscHeader::ref_from_bytes(&self.raw_boot[..size_of::<DiscHeader>()])
.expect("Invalid disc header alignment")
}

/// A view into the partition header.
#[inline]
pub fn partition_header(&self) -> &PartitionHeader {
PartitionHeader::ref_from_bytes(&self.raw_boot[size_of::<DiscHeader>()..])
.expect("Invalid partition header alignment")
}

/// A view into the file system table (FST).
#[inline]
pub fn fst(&self) -> Option<Fst> {
// FST has already been parsed, so we can safely unwrap
Some(Fst::new(self.raw_fst.as_deref()?).unwrap())
}
}
43 changes: 25 additions & 18 deletions nod/src/disc/gcn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use std::{
sync::Arc,
};

use zerocopy::FromBytes;
use zerocopy::{FromBytes, FromZeros, IntoBytes};

use crate::{
disc::{
Expand All @@ -17,7 +17,7 @@ use crate::{
read::{PartitionEncryption, PartitionMeta, PartitionReader},
util::{
impl_read_for_bufread,
read::{read_arc, read_arc_slice, read_vec},
read::{read_arc, read_arc_slice, read_from},
},
Result, ResultContext,
};
Expand Down Expand Up @@ -138,17 +138,16 @@ pub(crate) fn read_dol(
reader
.seek(SeekFrom::Start(partition_header.dol_offset(is_wii)))
.context("Seeking to DOL offset")?;
let mut raw_dol: Vec<u8> =
read_vec(reader, size_of::<DolHeader>()).context("Reading DOL header")?;
let dol_header = DolHeader::ref_from_bytes(raw_dol.as_slice()).unwrap();
let dol_header: DolHeader = read_from(reader).context("Reading DOL header")?;
let dol_size = (dol_header.text_offs.iter().zip(&dol_header.text_sizes))
.chain(dol_header.data_offs.iter().zip(&dol_header.data_sizes))
.map(|(offs, size)| offs.get() + size.get())
.max()
.unwrap_or(size_of::<DolHeader>() as u32);
raw_dol.resize(dol_size as usize, 0);
let mut raw_dol = <[u8]>::new_box_zeroed_with_elems(dol_size as usize)?;
raw_dol[..size_of::<DolHeader>()].copy_from_slice(dol_header.as_bytes());
reader.read_exact(&mut raw_dol[size_of::<DolHeader>()..]).context("Reading DOL")?;
Ok(Arc::from(raw_dol.as_slice()))
Ok(Arc::from(raw_dol))
}

pub(crate) fn read_fst<R>(
Expand All @@ -173,6 +172,24 @@ where
Ok(raw_fst)
}

pub(crate) fn read_apploader<R>(reader: &mut R) -> Result<Arc<[u8]>>
where R: Read + Seek + ?Sized {
reader
.seek(SeekFrom::Start(BOOT_SIZE as u64 + BI2_SIZE as u64))
.context("Seeking to apploader offset")?;
let apploader_header: ApploaderHeader =
read_from(reader).context("Reading apploader header")?;
let apploader_size = size_of::<ApploaderHeader>()
+ apploader_header.size.get() as usize
+ apploader_header.trailer_size.get() as usize;
let mut raw_apploader = <[u8]>::new_box_zeroed_with_elems(apploader_size)?;
raw_apploader[..size_of::<ApploaderHeader>()].copy_from_slice(apploader_header.as_bytes());
reader
.read_exact(&mut raw_apploader[size_of::<ApploaderHeader>()..])
.context("Reading apploader")?;
Ok(Arc::from(raw_apploader))
}

pub(crate) fn read_part_meta(
reader: &mut dyn PartitionReader,
is_wii: bool,
Expand All @@ -186,17 +203,7 @@ pub(crate) fn read_part_meta(
let raw_bi2: Arc<[u8; BI2_SIZE]> = read_arc(reader).context("Reading bi2.bin")?;

// apploader.bin
let mut raw_apploader: Vec<u8> =
read_vec(reader, size_of::<ApploaderHeader>()).context("Reading apploader header")?;
let apploader_header = ApploaderHeader::ref_from_bytes(raw_apploader.as_slice()).unwrap();
let apploader_size = size_of::<ApploaderHeader>()
+ apploader_header.size.get() as usize
+ apploader_header.trailer_size.get() as usize;
raw_apploader.resize(apploader_size, 0);
reader
.read_exact(&mut raw_apploader[size_of::<ApploaderHeader>()..])
.context("Reading apploader")?;
let raw_apploader = Arc::from(raw_apploader.as_slice());
let raw_apploader = read_apploader(reader)?;

// fst.bin
let raw_fst = read_fst(reader, partition_header, is_wii)?;
Expand Down
2 changes: 1 addition & 1 deletion nod/src/disc/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ pub const DOL_MAX_TEXT_SECTIONS: usize = 7;
pub const DOL_MAX_DATA_SECTIONS: usize = 11;

/// Dolphin executable (DOL) header.
#[derive(Debug, Clone, FromBytes, Immutable, KnownLayout)]
#[derive(Debug, Clone, FromBytes, IntoBytes, Immutable, KnownLayout)]
pub struct DolHeader {
/// Text section offsets
pub text_offs: [U32; DOL_MAX_TEXT_SECTIONS],
Expand Down
2 changes: 1 addition & 1 deletion nod/src/disc/preloader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -415,7 +415,7 @@ impl SectorGroupLoader {
sector_data,
self.block_buf.as_mut(),
abs_sector,
&partition.disc_header,
partition.disc_header(),
Some(partition),
)?;
if !encrypted {
Expand Down
Loading

0 comments on commit 1e44f23

Please sign in to comment.