mirror of
https://github.com/xavo95/repak.git
synced 2025-01-18 19:04:07 +00:00
add compression and oodle features
This commit is contained in:
parent
03dd3a63ed
commit
f2c2255d53
6 changed files with 40 additions and 15 deletions
|
@ -6,19 +6,24 @@ license.workspace = true
|
||||||
version.workspace = true
|
version.workspace = true
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
|
|
||||||
|
[features]
|
||||||
|
default = ["compression"]
|
||||||
|
compression = ["dep:flate2", "dep:zstd"]
|
||||||
|
oodle = ["dep:libloading", "dep:ureq", "dep:once_cell", "dep:hex-literal", "dep:hex"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
byteorder = "1.4"
|
byteorder = "1.4"
|
||||||
aes = "0.8"
|
aes = "0.8"
|
||||||
flate2 = "1.0"
|
flate2 = { version = "1.0", optional = true }
|
||||||
|
zstd = { version = "0.12", optional = true }
|
||||||
thiserror = "1.0"
|
thiserror = "1.0"
|
||||||
sha1 = "0.10.5"
|
sha1 = "0.10.5"
|
||||||
strum = { workspace = true }
|
strum = { workspace = true }
|
||||||
libloading = "0.7.4"
|
libloading = { version = "0.7", optional = true }
|
||||||
ureq = "2.6.2"
|
ureq = { version = "2.6", optional = true }
|
||||||
hex-literal = "0.4.1"
|
once_cell = { version = "1.17", optional = true}
|
||||||
hex = { workspace = true }
|
hex-literal = { version = "0.4", optional = true }
|
||||||
once_cell = "1.17.1"
|
hex = { workspace = true, optional = true }
|
||||||
zstd = "0.12.3"
|
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
base64 = { workspace = true }
|
base64 = { workspace = true }
|
||||||
|
|
|
@ -350,6 +350,7 @@ impl Entry {
|
||||||
None => vec![0..data.len()],
|
None => vec![0..data.len()],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[cfg(feature = "compression")]
|
||||||
macro_rules! decompress {
|
macro_rules! decompress {
|
||||||
($decompressor: ty) => {
|
($decompressor: ty) => {
|
||||||
for range in ranges {
|
for range in ranges {
|
||||||
|
@ -359,14 +360,18 @@ impl Entry {
|
||||||
}
|
}
|
||||||
|
|
||||||
match self.compression.map(|c| compression[c as usize]) {
|
match self.compression.map(|c| compression[c as usize]) {
|
||||||
None => buf.write_all(&data)?,
|
None | Some(Compression::None) => buf.write_all(&data)?,
|
||||||
|
#[cfg(feature = "compression")]
|
||||||
Some(Compression::Zlib) => decompress!(flate2::read::ZlibDecoder<&[u8]>),
|
Some(Compression::Zlib) => decompress!(flate2::read::ZlibDecoder<&[u8]>),
|
||||||
|
#[cfg(feature = "compression")]
|
||||||
Some(Compression::Gzip) => decompress!(flate2::read::GzDecoder<&[u8]>),
|
Some(Compression::Gzip) => decompress!(flate2::read::GzDecoder<&[u8]>),
|
||||||
|
#[cfg(feature = "compression")]
|
||||||
Some(Compression::Zstd) => {
|
Some(Compression::Zstd) => {
|
||||||
for range in ranges {
|
for range in ranges {
|
||||||
io::copy(&mut zstd::stream::read::Decoder::new(&data[range])?, buf)?;
|
io::copy(&mut zstd::stream::read::Decoder::new(&data[range])?, buf)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[cfg(feature = "oodle")]
|
||||||
Some(Compression::Oodle) => {
|
Some(Compression::Oodle) => {
|
||||||
#[cfg(not(target_os = "windows"))]
|
#[cfg(not(target_os = "windows"))]
|
||||||
return Err(super::Error::Oodle);
|
return Err(super::Error::Oodle);
|
||||||
|
@ -472,18 +477,25 @@ impl Entry {
|
||||||
buf.write_all(&decompressed)?;
|
buf.write_all(&decompressed)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => todo!(),
|
#[cfg(not(feature = "oodle"))]
|
||||||
|
Some(Compression::Oodle) => return Err(super::Error::Oodle),
|
||||||
|
#[cfg(not(feature = "compression"))]
|
||||||
|
_ => return Err(super::Error::Compression),
|
||||||
}
|
}
|
||||||
buf.flush()?;
|
buf.flush()?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "oodle")]
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
|
#[cfg(feature = "oodle")]
|
||||||
static OODLE: Lazy<Result<libloading::Library, String>> =
|
static OODLE: Lazy<Result<libloading::Library, String>> =
|
||||||
Lazy::new(|| get_oodle().map_err(|e| e.to_string()));
|
Lazy::new(|| get_oodle().map_err(|e| e.to_string()));
|
||||||
|
#[cfg(feature = "oodle")]
|
||||||
static OODLE_HASH: [u8; 20] = hex_literal::hex!("4bcc73614cb8fd2b0bce8d0f91ee5f3202d9d624");
|
static OODLE_HASH: [u8; 20] = hex_literal::hex!("4bcc73614cb8fd2b0bce8d0f91ee5f3202d9d624");
|
||||||
|
|
||||||
|
#[cfg(feature = "oodle")]
|
||||||
fn get_oodle() -> Result<libloading::Library, super::Error> {
|
fn get_oodle() -> Result<libloading::Library, super::Error> {
|
||||||
use sha1::{Digest, Sha1};
|
use sha1::{Digest, Sha1};
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,13 @@ pub enum Error {
|
||||||
#[error("expect 256 bit AES key as base64 or hex string")]
|
#[error("expect 256 bit AES key as base64 or hex string")]
|
||||||
Aes,
|
Aes,
|
||||||
|
|
||||||
|
// feature errors
|
||||||
|
#[error("enable the compression feature to read compressed paks")]
|
||||||
|
Compression,
|
||||||
|
|
||||||
|
#[error("enable the oodle feature to read oodle paks")]
|
||||||
|
Oodle,
|
||||||
|
|
||||||
// std errors
|
// std errors
|
||||||
#[error("io error: {0}")]
|
#[error("io error: {0}")]
|
||||||
Io(#[from] std::io::Error),
|
Io(#[from] std::io::Error),
|
||||||
|
@ -22,6 +29,7 @@ pub enum Error {
|
||||||
#[error("utf16 conversion: {0}")]
|
#[error("utf16 conversion: {0}")]
|
||||||
Utf16(#[from] std::string::FromUtf16Error),
|
Utf16(#[from] std::string::FromUtf16Error),
|
||||||
|
|
||||||
|
#[cfg(feature = "oodle")]
|
||||||
#[error("ureq error: {0}")]
|
#[error("ureq error: {0}")]
|
||||||
Ureq(#[from] Box<ureq::Error>), // boxed because ureq::Error is quite large
|
Ureq(#[from] Box<ureq::Error>), // boxed because ureq::Error is quite large
|
||||||
|
|
||||||
|
@ -35,9 +43,6 @@ pub enum Error {
|
||||||
#[error("found magic of {0:#x} instead of {:#x}", super::MAGIC)]
|
#[error("found magic of {0:#x} instead of {:#x}", super::MAGIC)]
|
||||||
Magic(u32),
|
Magic(u32),
|
||||||
|
|
||||||
#[error("Oodle compression only supported on Windows (or WINE)")]
|
|
||||||
Oodle,
|
|
||||||
|
|
||||||
#[error("Could not load oo2core_9_win64.dll")]
|
#[error("Could not load oo2core_9_win64.dll")]
|
||||||
OodleFailed,
|
OodleFailed,
|
||||||
|
|
||||||
|
@ -72,7 +77,7 @@ pub enum Error {
|
||||||
OsString(std::ffi::OsString),
|
OsString(std::ffi::OsString),
|
||||||
|
|
||||||
#[error("{0}version unsupported or is encrypted (possibly missing --aes-key?)")]
|
#[error("{0}version unsupported or is encrypted (possibly missing --aes-key?)")]
|
||||||
UnsuportedOrEncrypted(String),
|
UnsupportedOrEncrypted(String),
|
||||||
|
|
||||||
#[error("{0}")]
|
#[error("{0}")]
|
||||||
Other(String),
|
Other(String),
|
||||||
|
|
|
@ -7,6 +7,9 @@ mod pak;
|
||||||
|
|
||||||
pub use {error::*, pak::*};
|
pub use {error::*, pak::*};
|
||||||
|
|
||||||
|
#[cfg(all(feature = "oodle", not(target_os = "windows")))]
|
||||||
|
compile_error!("Oodle compression only supported on Windows (or WINE)");
|
||||||
|
|
||||||
pub const MAGIC: u32 = 0x5A6F12E1;
|
pub const MAGIC: u32 = 0x5A6F12E1;
|
||||||
|
|
||||||
#[derive(
|
#[derive(
|
||||||
|
|
|
@ -96,7 +96,7 @@ impl PakReader {
|
||||||
Err(err) => writeln!(log, "trying version {} failed: {}", ver, err)?,
|
Err(err) => writeln!(log, "trying version {} failed: {}", ver, err)?,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(super::Error::UnsuportedOrEncrypted(log))
|
Err(super::Error::UnsupportedOrEncrypted(log))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new<R: Read + Seek>(
|
pub fn new<R: Read + Seek>(
|
||||||
|
|
|
@ -19,6 +19,6 @@ indicatif = { version = "0.17.3", features = ["rayon"] }
|
||||||
path-clean = "0.1.0"
|
path-clean = "0.1.0"
|
||||||
path-slash = "0.2.1"
|
path-slash = "0.2.1"
|
||||||
rayon = "1.6.1"
|
rayon = "1.6.1"
|
||||||
repak = { version = "0.1.7", path = "../repak" }
|
repak = { version = "0.1.7", path = "../repak", features = ["oodle"] }
|
||||||
sha2 = "0.10.7"
|
sha2 = "0.10.7"
|
||||||
strum = { workspace = true }
|
strum = { workspace = true }
|
||||||
|
|
Loading…
Reference in a new issue