mirror of https://github.com/encounter/nod-rs.git
Release 0.1.1: Improvements to windowed stream API, minor fixes
This commit is contained in:
parent
1e60c551e1
commit
9df1aa4149
|
@ -1,2 +1,3 @@
|
||||||
/target
|
/target
|
||||||
Cargo.lock
|
Cargo.lock
|
||||||
|
.idea
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "nod"
|
name = "nod"
|
||||||
version = "0.1.0"
|
version = "0.1.1"
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
authors = ["Luke Street <luke@street.dev>"]
|
authors = ["Luke Street <luke@street.dev>"]
|
||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# nod-rs [![Build Status]][actions] [![Latest Version]][crates.io] [![Api Rustdoc]][rustdoc] [![Rust](https://img.shields.io/badge/rust-1.51%2B-blue.svg?maxAge=3600)](https://github.com/encounter/nod-rs)
|
# nod-rs [![Build Status]][actions] [![Latest Version]][crates.io] [![Api Rustdoc]][rustdoc] ![Rust Version]
|
||||||
|
|
||||||
[Build Status]: https://github.com/encounter/nod-rs/workflows/build/badge.svg
|
[Build Status]: https://github.com/encounter/nod-rs/workflows/build/badge.svg
|
||||||
[actions]: https://github.com/encounter/nod-rs/actions
|
[actions]: https://github.com/encounter/nod-rs/actions
|
||||||
|
@ -6,6 +6,7 @@
|
||||||
[crates.io]: https://crates.io/crates/nod
|
[crates.io]: https://crates.io/crates/nod
|
||||||
[Api Rustdoc]: https://img.shields.io/badge/api-rustdoc-blue.svg
|
[Api Rustdoc]: https://img.shields.io/badge/api-rustdoc-blue.svg
|
||||||
[rustdoc]: https://docs.rs/nod
|
[rustdoc]: https://docs.rs/nod
|
||||||
|
[Rust Version]: https://img.shields.io/badge/rust-1.51+-blue.svg?maxAge=3600
|
||||||
|
|
||||||
Library for traversing & reading GameCube and Wii disc images.
|
Library for traversing & reading GameCube and Wii disc images.
|
||||||
|
|
||||||
|
|
|
@ -100,13 +100,7 @@ impl<'a> ReadStream for GCPartReadStream<'a> {
|
||||||
impl<'a> PartReadStream for GCPartReadStream<'a> {
|
impl<'a> PartReadStream for GCPartReadStream<'a> {
|
||||||
fn begin_file_stream(&mut self, node: &Node) -> io::Result<SharedWindowedReadStream> {
|
fn begin_file_stream(&mut self, node: &Node) -> io::Result<SharedWindowedReadStream> {
|
||||||
assert_eq!(node.kind, NodeKind::File);
|
assert_eq!(node.kind, NodeKind::File);
|
||||||
let offset = node.offset as u64;
|
io::Result::Ok(self.new_window(node.offset as u64, node.length as u64)?)
|
||||||
self.seek(SeekFrom::Start(offset))?;
|
|
||||||
io::Result::Ok(SharedWindowedReadStream {
|
|
||||||
base: self,
|
|
||||||
begin: offset,
|
|
||||||
end: offset + node.length as u64,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_header(&mut self) -> Result<Box<dyn PartHeader>> {
|
fn read_header(&mut self) -> Result<Box<dyn PartHeader>> {
|
||||||
|
|
|
@ -8,7 +8,7 @@ use sha1::{digest, Digest, Sha1};
|
||||||
use crate::disc::{BI2Header, BUFFER_SIZE, DiscBase, DiscIO, Header, PartHeader, PartReadStream};
|
use crate::disc::{BI2Header, BUFFER_SIZE, DiscBase, DiscIO, Header, PartHeader, PartReadStream};
|
||||||
use crate::{Error, div_rem, Result, array_ref};
|
use crate::{Error, div_rem, Result, array_ref};
|
||||||
use crate::fst::{find_node, Node, NodeKind, NodeType, node_parser};
|
use crate::fst::{find_node, Node, NodeKind, NodeType, node_parser};
|
||||||
use crate::streams::{OwningWindowedReadStream, ReadStream, SharedWindowedReadStream};
|
use crate::streams::{OwningWindowedReadStream, ReadStream, SharedWindowedReadStream, wrap_windowed};
|
||||||
|
|
||||||
type Aes128Cbc = Cbc<Aes128, NoPadding>;
|
type Aes128Cbc = Cbc<Aes128, NoPadding>;
|
||||||
|
|
||||||
|
@ -218,11 +218,10 @@ impl DiscBase for DiscWii {
|
||||||
.ok_or(Error::DiscFormat("Failed to locate data partition".to_string()))?;
|
.ok_or(Error::DiscFormat("Failed to locate data partition".to_string()))?;
|
||||||
let data_off = part.part_header.data_off;
|
let data_off = part.part_header.data_off;
|
||||||
let result = Box::new(WiiPartReadStream {
|
let result = Box::new(WiiPartReadStream {
|
||||||
stream: OwningWindowedReadStream {
|
stream: wrap_windowed(
|
||||||
base: disc_io.begin_read_stream(data_off)?,
|
disc_io.begin_read_stream(data_off)?,
|
||||||
begin: data_off,
|
data_off, part.part_header.data_size,
|
||||||
end: data_off + part.part_header.data_size,
|
)?,
|
||||||
},
|
|
||||||
crypto: if disc_io.has_wii_crypto() {
|
crypto: if disc_io.has_wii_crypto() {
|
||||||
Aes128::new(&part.part_header.ticket.enc_key.into()).into()
|
Aes128::new(&part.part_header.ticket.enc_key.into()).into()
|
||||||
} else { Option::None },
|
} else { Option::None },
|
||||||
|
@ -247,13 +246,7 @@ struct WiiPartReadStream<'a> {
|
||||||
impl<'a> PartReadStream for WiiPartReadStream<'a> {
|
impl<'a> PartReadStream for WiiPartReadStream<'a> {
|
||||||
fn begin_file_stream(&mut self, node: &Node) -> io::Result<SharedWindowedReadStream> {
|
fn begin_file_stream(&mut self, node: &Node) -> io::Result<SharedWindowedReadStream> {
|
||||||
assert_eq!(node.kind, NodeKind::File);
|
assert_eq!(node.kind, NodeKind::File);
|
||||||
let offset = (node.offset as u64) << 2;
|
io::Result::Ok(self.new_window((node.offset as u64) << 2, node.length as u64)?)
|
||||||
self.seek(SeekFrom::Start(offset))?;
|
|
||||||
io::Result::Ok(SharedWindowedReadStream {
|
|
||||||
base: self,
|
|
||||||
begin: offset,
|
|
||||||
end: offset + node.length as u64,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_header(&mut self) -> Result<Box<dyn PartHeader>> {
|
fn read_header(&mut self) -> Result<Box<dyn PartHeader>> {
|
||||||
|
|
|
@ -167,9 +167,9 @@ impl<'a> NFSReadStream<'a> {
|
||||||
let iv: [u8; 16] = [
|
let iv: [u8; 16] = [
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
(phys_addr.l_block & 0xFF) as u8,
|
(phys_addr.l_block & 0xFF) as u8,
|
||||||
((phys_addr.l_block >> 2) & 0xFF) as u8,
|
((phys_addr.l_block >> 8) & 0xFF) as u8,
|
||||||
((phys_addr.l_block >> 4) & 0xFF) as u8,
|
((phys_addr.l_block >> 16) & 0xFF) as u8,
|
||||||
((phys_addr.l_block >> 6) & 0xFF) as u8,
|
((phys_addr.l_block >> 24) & 0xFF) as u8,
|
||||||
];
|
];
|
||||||
Aes128Cbc::new(self.crypto.clone(), &iv.into())
|
Aes128Cbc::new(self.crypto.clone(), &iv.into())
|
||||||
.decrypt(&mut self.buf)?;
|
.decrypt(&mut self.buf)?;
|
||||||
|
|
|
@ -20,6 +20,18 @@ pub trait ReadStream: Read + Seek {
|
||||||
///
|
///
|
||||||
/// <https://github.com/rust-lang/rust/issues/59359>
|
/// <https://github.com/rust-lang/rust/issues/59359>
|
||||||
fn stable_stream_len(&mut self) -> io::Result<u64>;
|
fn stable_stream_len(&mut self) -> io::Result<u64>;
|
||||||
|
|
||||||
|
/// Creates a windowed read sub-stream with offset and size.
|
||||||
|
///
|
||||||
|
/// Seeks underlying stream immediately.
|
||||||
|
fn new_window(&mut self, offset: u64, size: u64) -> io::Result<SharedWindowedReadStream> where Self: Sized {
|
||||||
|
self.seek(SeekFrom::Start(offset))?;
|
||||||
|
io::Result::Ok(SharedWindowedReadStream {
|
||||||
|
base: self,
|
||||||
|
begin: offset,
|
||||||
|
end: offset + size,
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ReadStream for File {
|
impl ReadStream for File {
|
||||||
|
@ -38,15 +50,25 @@ trait WindowedReadStream: ReadStream {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct OwningWindowedReadStream<'a> {
|
pub struct OwningWindowedReadStream<'a> {
|
||||||
pub(crate) base: Box<dyn ReadStream + 'a>,
|
pub base: Box<dyn ReadStream + 'a>,
|
||||||
pub(crate) begin: u64,
|
pub begin: u64,
|
||||||
pub(crate) end: u64,
|
pub end: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Takes ownership of & wraps a read stream into a windowed read stream.
|
||||||
|
pub fn wrap_windowed<'a>(mut base: Box<dyn ReadStream + 'a>, offset: u64, size: u64) -> io::Result<OwningWindowedReadStream<'a>> {
|
||||||
|
base.seek(SeekFrom::Start(offset))?;
|
||||||
|
io::Result::Ok(OwningWindowedReadStream {
|
||||||
|
base,
|
||||||
|
begin: offset,
|
||||||
|
end: offset + size,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct SharedWindowedReadStream<'a> {
|
pub struct SharedWindowedReadStream<'a> {
|
||||||
pub(crate) base: &'a mut dyn ReadStream,
|
pub base: &'a mut dyn ReadStream,
|
||||||
pub(crate) begin: u64,
|
pub begin: u64,
|
||||||
pub(crate) end: u64,
|
pub end: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
|
|
Loading…
Reference in New Issue