mirror of
https://github.com/encounter/nod-rs.git
synced 2025-12-12 06:45:08 +00:00
Fixes & bump to version 1.0.0
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "nod"
|
||||
version = "0.2.0"
|
||||
version = "1.0.0"
|
||||
edition = "2021"
|
||||
rust-version = "1.73.0"
|
||||
authors = ["Luke Street <luke@street.dev>"]
|
||||
@@ -23,20 +23,20 @@ compress-zlib = ["adler", "miniz_oxide"]
|
||||
compress-zstd = ["zstd"]
|
||||
|
||||
[dependencies]
|
||||
adler = { version = "1.0.2", optional = true }
|
||||
aes = "0.8.4"
|
||||
base16ct = "0.2.0"
|
||||
bzip2 = { version = "0.4.4", features = ["static"], optional = true }
|
||||
cbc = "0.1.2"
|
||||
digest = "0.10.7"
|
||||
dyn-clone = "1.0.16"
|
||||
encoding_rs = "0.8.33"
|
||||
itertools = "0.12.1"
|
||||
liblzma = { version = "0.2.3", features = ["static"], optional = true }
|
||||
log = "0.4.20"
|
||||
miniz_oxide = { version = "0.7.2", optional = true }
|
||||
rayon = "1.8.1"
|
||||
sha1 = "0.10.6"
|
||||
thiserror = "1.0.57"
|
||||
zerocopy = { version = "0.7.32", features = ["alloc", "derive"] }
|
||||
zstd = { version = "0.13.0", optional = true }
|
||||
adler = { version = "1.0", optional = true }
|
||||
aes = "0.8"
|
||||
base16ct = "0.2"
|
||||
bzip2 = { version = "0.4", features = ["static"], optional = true }
|
||||
cbc = "0.1"
|
||||
digest = "0.10"
|
||||
dyn-clone = "1.0"
|
||||
encoding_rs = "0.8"
|
||||
itertools = "0.12"
|
||||
liblzma = { version = "0.2", features = ["static"], optional = true }
|
||||
log = "0.4"
|
||||
miniz_oxide = { version = "0.7", optional = true }
|
||||
rayon = "1.8"
|
||||
sha1 = "0.10"
|
||||
thiserror = "1.0"
|
||||
zerocopy = { version = "0.7", features = ["alloc", "derive"] }
|
||||
zstd = { version = "0.13", optional = true }
|
||||
|
||||
@@ -118,7 +118,7 @@ impl PartitionBase for PartitionGC {
|
||||
|
||||
fn open_file(&mut self, node: &Node) -> io::Result<SharedWindowedReadStream> {
|
||||
assert_eq!(node.kind(), NodeKind::File);
|
||||
self.new_window(node.offset(false), node.length(false))
|
||||
self.new_window(node.offset(false), node.length())
|
||||
}
|
||||
|
||||
fn ideal_buffer_size(&self) -> usize { SECTOR_SIZE }
|
||||
|
||||
@@ -437,7 +437,7 @@ impl PartitionBase for PartitionWii {
|
||||
|
||||
fn open_file(&mut self, node: &Node) -> io::Result<SharedWindowedReadStream> {
|
||||
assert_eq!(node.kind(), NodeKind::File);
|
||||
self.new_window(node.offset(true), node.length(true))
|
||||
self.new_window(node.offset(true), node.length())
|
||||
}
|
||||
|
||||
fn ideal_buffer_size(&self) -> usize { SECTOR_DATA_SIZE }
|
||||
|
||||
@@ -63,18 +63,12 @@ impl Node {
|
||||
}
|
||||
}
|
||||
|
||||
/// For files, this is the byte size of the file. (Wii: >> 2)
|
||||
/// For files, this is the byte size of the file.
|
||||
///
|
||||
/// For directories, this is the child end index in the FST.
|
||||
///
|
||||
/// Number of child files and directories recursively is `length - offset`.
|
||||
pub fn length(&self, is_wii: bool) -> u64 {
|
||||
if is_wii && self.kind == 0 {
|
||||
self.length.get() as u64 * 4
|
||||
} else {
|
||||
self.length.get() as u64
|
||||
}
|
||||
}
|
||||
pub fn length(&self) -> u64 { self.length.get() as u64 }
|
||||
}
|
||||
|
||||
/// A view into the file system tree (FST).
|
||||
@@ -90,7 +84,7 @@ impl<'a> Fst<'a> {
|
||||
return Err("FST root node not found");
|
||||
};
|
||||
// String table starts after the last node
|
||||
let string_base = root_node.length(false) * size_of::<Node>() as u64;
|
||||
let string_base = root_node.length() * size_of::<Node>() as u64;
|
||||
if string_base >= buf.len() as u64 {
|
||||
return Err("FST string table out of bounds");
|
||||
}
|
||||
@@ -137,10 +131,10 @@ impl<'a> Fst<'a> {
|
||||
}
|
||||
// Descend into directory
|
||||
idx += 1;
|
||||
stop_at = Some(node.length(false) as usize + idx);
|
||||
stop_at = Some(node.length() as usize + idx);
|
||||
} else if node.is_dir() {
|
||||
// Skip directory
|
||||
idx = node.length(false) as usize;
|
||||
idx = node.length() as usize;
|
||||
} else {
|
||||
// Skip file
|
||||
idx += 1;
|
||||
|
||||
@@ -102,7 +102,7 @@ impl BlockIO for DiscIOCISO {
|
||||
let phys_block = self.block_map[block as usize];
|
||||
if phys_block == u16::MAX {
|
||||
// Check if block is junk data
|
||||
if self.nkit_header.as_ref().is_some_and(|h| h.is_junk_block(block).unwrap_or(false)) {
|
||||
if self.nkit_header.as_ref().and_then(|h| h.is_junk_block(block)).unwrap_or(false) {
|
||||
return Ok(Block::Junk);
|
||||
};
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@ pub struct DiscIOWBFS {
|
||||
/// WBFS header
|
||||
header: WBFSHeader,
|
||||
/// Map of Wii LBAs to WBFS LBAs
|
||||
block_table: Box<[U16]>,
|
||||
block_map: Box<[U16]>,
|
||||
/// Optional NKit header
|
||||
nkit_header: Option<NKitHeader>,
|
||||
}
|
||||
@@ -91,11 +91,11 @@ impl DiscIOWBFS {
|
||||
return Err(Error::DiscFormat("Only single WBFS discs are supported".to_string()));
|
||||
}
|
||||
|
||||
// Read WBFS LBA table
|
||||
// Read WBFS LBA map
|
||||
inner
|
||||
.seek(SeekFrom::Start(header.sector_size() as u64 + DISC_HEADER_SIZE as u64))
|
||||
.context("Seeking to WBFS LBA table")?; // Skip header
|
||||
let block_table: Box<[U16]> = read_box_slice(&mut inner, header.max_blocks() as usize)
|
||||
let block_map: Box<[U16]> = read_box_slice(&mut inner, header.max_blocks() as usize)
|
||||
.context("Reading WBFS LBA table")?;
|
||||
|
||||
// Read NKit header if present (always at 0x10000)
|
||||
@@ -104,7 +104,7 @@ impl DiscIOWBFS {
|
||||
|
||||
// Reset reader
|
||||
inner.reset();
|
||||
Ok(Box::new(Self { inner, header, block_table, nkit_header }))
|
||||
Ok(Box::new(Self { inner, header, block_map, nkit_header }))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,16 +120,20 @@ impl BlockIO for DiscIOWBFS {
|
||||
return Ok(Block::Zero);
|
||||
}
|
||||
|
||||
// Check if block is junk data
|
||||
if self.nkit_header.as_ref().and_then(|h| h.is_junk_block(block)).unwrap_or(false) {
|
||||
return Ok(Block::Junk);
|
||||
// Find the block in the map
|
||||
let phys_block = self.block_map[block as usize].get();
|
||||
if phys_block == 0 {
|
||||
// Check if block is junk data
|
||||
if self.nkit_header.as_ref().and_then(|h| h.is_junk_block(block)).unwrap_or(false) {
|
||||
return Ok(Block::Junk);
|
||||
}
|
||||
|
||||
// Otherwise, read zeroes
|
||||
return Ok(Block::Zero);
|
||||
}
|
||||
|
||||
// Read block
|
||||
let block_start = block_size as u64 * self.block_table[block as usize].get() as u64;
|
||||
if block_start == 0 {
|
||||
return Ok(Block::Zero);
|
||||
}
|
||||
let block_start = block_size as u64 * phys_block as u64;
|
||||
self.inner.seek(SeekFrom::Start(block_start))?;
|
||||
self.inner.read_exact(out)?;
|
||||
Ok(Block::Raw)
|
||||
|
||||
Reference in New Issue
Block a user