refactor: Extract Oodle into separate library
The library utilizes an internal global singleton to allow using the functions without having to lug around an instance of `libloading::Library`.
This commit is contained in:
parent
5eebced362
commit
9f84340b73
17 changed files with 184 additions and 102 deletions
11
Cargo.lock
generated
11
Cargo.lock
generated
|
@ -378,6 +378,7 @@ dependencies = [
|
||||||
"glob",
|
"glob",
|
||||||
"libloading",
|
"libloading",
|
||||||
"nanorand",
|
"nanorand",
|
||||||
|
"oodle-sys",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"promptly",
|
"promptly",
|
||||||
"sdk",
|
"sdk",
|
||||||
|
@ -840,6 +841,15 @@ version = "1.17.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66"
|
checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "oodle-sys"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"libloading",
|
||||||
|
"thiserror",
|
||||||
|
"tracing",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "opaque-debug"
|
name = "opaque-debug"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
|
@ -1096,6 +1106,7 @@ dependencies = [
|
||||||
"glob",
|
"glob",
|
||||||
"libloading",
|
"libloading",
|
||||||
"nanorand",
|
"nanorand",
|
||||||
|
"oodle-sys",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_sjson",
|
"serde_sjson",
|
||||||
|
|
|
@ -15,6 +15,7 @@ libloading = "0.7.4"
|
||||||
nanorand = "0.7.0"
|
nanorand = "0.7.0"
|
||||||
pin-project-lite = "0.2.9"
|
pin-project-lite = "0.2.9"
|
||||||
serde = { version = "1.0.147", features = ["derive"] }
|
serde = { version = "1.0.147", features = ["derive"] }
|
||||||
|
oodle-sys = { path = "../../lib/oodle-sys", version = "*" }
|
||||||
serde_sjson = { path = "../../lib/serde_sjson", version = "*" }
|
serde_sjson = { path = "../../lib/serde_sjson", version = "*" }
|
||||||
tokio = { version = "1.21.2", features = ["rt-multi-thread", "fs", "process", "macros", "tracing", "io-util", "io-std"] }
|
tokio = { version = "1.21.2", features = ["rt-multi-thread", "fs", "process", "macros", "tracing", "io-util", "io-std"] }
|
||||||
tokio-stream = { version = "0.1.11", features = ["fs", "io-util"] }
|
tokio-stream = { version = "0.1.11", features = ["fs", "io-util"] }
|
||||||
|
|
|
@ -7,7 +7,7 @@ use color_eyre::{Help, Report};
|
||||||
use futures::future::try_join_all;
|
use futures::future::try_join_all;
|
||||||
use futures::StreamExt;
|
use futures::StreamExt;
|
||||||
use sdk::filetype::package::Package;
|
use sdk::filetype::package::Package;
|
||||||
use sdk::{Bundle, BundleFile, Oodle};
|
use sdk::{Bundle, BundleFile};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use tokio::fs::{self, File};
|
use tokio::fs::{self, File};
|
||||||
use tokio::io::AsyncReadExt;
|
use tokio::io::AsyncReadExt;
|
||||||
|
@ -28,17 +28,12 @@ pub(crate) fn command_definition() -> Command {
|
||||||
If omitted, dtmt will search from the current working directory upward.",
|
If omitted, dtmt will search from the current working directory upward.",
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(Arg::new("oodle").long("oodle").help(
|
||||||
Arg::new("oodle")
|
|
||||||
.long("oodle")
|
|
||||||
.default_value(super::OODLE_LIB_NAME)
|
|
||||||
.help(
|
|
||||||
"The oodle library to load. This may either be:\n\
|
"The oodle library to load. This may either be:\n\
|
||||||
- A library name that will be searched for in the system's default paths.\n\
|
- A library name that will be searched for in the system's default paths.\n\
|
||||||
- A file path relative to the current working directory.\n\
|
- A file path relative to the current working directory.\n\
|
||||||
- An absolute file path.",
|
- An absolute file path.",
|
||||||
),
|
))
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default, Deserialize)]
|
#[derive(Debug, Default, Deserialize)]
|
||||||
|
@ -175,10 +170,9 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument(skip_all)]
|
#[tracing::instrument(skip_all)]
|
||||||
pub(crate) async fn run(mut ctx: sdk::Context, matches: &ArgMatches) -> Result<()> {
|
pub(crate) async fn run(_ctx: sdk::Context, matches: &ArgMatches) -> Result<()> {
|
||||||
if let Some(name) = matches.get_one::<String>("oodle") {
|
unsafe {
|
||||||
let oodle = Oodle::new(name)?;
|
oodle_sys::init(matches.get_one::<String>("oodle"));
|
||||||
ctx.oodle = Some(oodle);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let cfg = {
|
let cfg = {
|
||||||
|
@ -237,7 +231,7 @@ pub(crate) async fn run(mut ctx: sdk::Context, matches: &ArgMatches) -> Result<(
|
||||||
}
|
}
|
||||||
|
|
||||||
archive
|
archive
|
||||||
.write(&ctx, dest.as_ref())
|
.write(dest.as_ref())
|
||||||
.wrap_err("failed to write mod archive")
|
.wrap_err("failed to write mod archive")
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
|
|
|
@ -98,7 +98,7 @@ pub(crate) async fn run(ctx: sdk::Context, matches: &ArgMatches) -> Result<()> {
|
||||||
|
|
||||||
let out_path = matches.get_one::<PathBuf>("output").unwrap_or(bundle_path);
|
let out_path = matches.get_one::<PathBuf>("output").unwrap_or(bundle_path);
|
||||||
let data = bundle
|
let data = bundle
|
||||||
.to_binary(&ctx)
|
.to_binary()
|
||||||
.wrap_err("failed to write changed bundle to output")?;
|
.wrap_err("failed to write changed bundle to output")?;
|
||||||
|
|
||||||
fs::write(out_path, &data)
|
fs::write(out_path, &data)
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
use clap::{Arg, ArgMatches, Command};
|
use clap::{Arg, ArgMatches, Command};
|
||||||
use color_eyre::eyre::Result;
|
use color_eyre::eyre::Result;
|
||||||
use sdk::Oodle;
|
|
||||||
|
|
||||||
mod decompress;
|
mod decompress;
|
||||||
mod extract;
|
mod extract;
|
||||||
|
@ -11,17 +10,12 @@ pub(crate) fn command_definition() -> Command {
|
||||||
Command::new("bundle")
|
Command::new("bundle")
|
||||||
.subcommand_required(true)
|
.subcommand_required(true)
|
||||||
.about("Manipulate the game's bundle files")
|
.about("Manipulate the game's bundle files")
|
||||||
.arg(
|
.arg(Arg::new("oodle").long("oodle").help(
|
||||||
Arg::new("oodle")
|
|
||||||
.long("oodle")
|
|
||||||
.default_value(super::OODLE_LIB_NAME)
|
|
||||||
.help(
|
|
||||||
"The oodle library to load. This may either be:\n\
|
"The oodle library to load. This may either be:\n\
|
||||||
- A library name that will be searched for in the system's default paths.\n\
|
- A library name that will be searched for in the system's default paths.\n\
|
||||||
- A file path relative to the current working directory.\n\
|
- A file path relative to the current working directory.\n\
|
||||||
- An absolute file path.",
|
- An absolute file path.",
|
||||||
),
|
))
|
||||||
)
|
|
||||||
.subcommand(decompress::command_definition())
|
.subcommand(decompress::command_definition())
|
||||||
.subcommand(extract::command_definition())
|
.subcommand(extract::command_definition())
|
||||||
.subcommand(inject::command_definition())
|
.subcommand(inject::command_definition())
|
||||||
|
@ -29,10 +23,9 @@ pub(crate) fn command_definition() -> Command {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument(skip_all)]
|
#[tracing::instrument(skip_all)]
|
||||||
pub(crate) async fn run(mut ctx: sdk::Context, matches: &ArgMatches) -> Result<()> {
|
pub(crate) async fn run(ctx: sdk::Context, matches: &ArgMatches) -> Result<()> {
|
||||||
if let Some(name) = matches.get_one::<String>("oodle") {
|
unsafe {
|
||||||
let oodle = Oodle::new(name)?;
|
oodle_sys::init(matches.get_one::<String>("oodle"));
|
||||||
ctx.oodle = Some(oodle);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
match matches.subcommand() {
|
match matches.subcommand() {
|
||||||
|
|
|
@ -18,12 +18,6 @@ use tracing_subscriber::prelude::*;
|
||||||
use tracing_subscriber::EnvFilter;
|
use tracing_subscriber::EnvFilter;
|
||||||
|
|
||||||
mod cmd {
|
mod cmd {
|
||||||
#[cfg(target_os = "windows")]
|
|
||||||
const OODLE_LIB_NAME: &str = "oo2core_8_win64";
|
|
||||||
|
|
||||||
#[cfg(target_os = "linux")]
|
|
||||||
const OODLE_LIB_NAME: &str = "liboo2corelinux64.so";
|
|
||||||
|
|
||||||
pub mod build;
|
pub mod build;
|
||||||
pub mod bundle;
|
pub mod bundle;
|
||||||
pub mod dictionary;
|
pub mod dictionary;
|
||||||
|
|
|
@ -32,7 +32,7 @@ impl Archive {
|
||||||
self.mod_file = Some(content);
|
self.mod_file = Some(content);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write<P>(&self, ctx: &sdk::Context, path: P) -> Result<()>
|
pub fn write<P>(&self, path: P) -> Result<()>
|
||||||
where
|
where
|
||||||
P: AsRef<Path>,
|
P: AsRef<Path>,
|
||||||
{
|
{
|
||||||
|
@ -76,7 +76,7 @@ impl Archive {
|
||||||
|
|
||||||
zip.start_file(path.to_string_lossy(), Default::default())?;
|
zip.start_file(path.to_string_lossy(), Default::default())?;
|
||||||
|
|
||||||
let data = bundle.to_binary(ctx)?;
|
let data = bundle.to_binary()?;
|
||||||
zip.write_all(&data)?;
|
zip.write_all(&data)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
2
lib/oodle-sys/.gitignore
vendored
Normal file
2
lib/oodle-sys/.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
/target
|
||||||
|
/Cargo.lock
|
11
lib/oodle-sys/Cargo.toml
Normal file
11
lib/oodle-sys/Cargo.toml
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
[package]
|
||||||
|
name = "oodle-sys"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
libloading = "0.7.4"
|
||||||
|
thiserror = "1.0.38"
|
||||||
|
tracing = "0.1.37"
|
77
lib/oodle-sys/src/lib.rs
Normal file
77
lib/oodle-sys/src/lib.rs
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
#![feature(c_size_t)]
|
||||||
|
#![feature(once_cell)]
|
||||||
|
|
||||||
|
use std::ffi::OsStr;
|
||||||
|
use std::sync::OnceLock;
|
||||||
|
|
||||||
|
mod library;
|
||||||
|
mod types;
|
||||||
|
|
||||||
|
pub use library::Library;
|
||||||
|
pub use library::CHUNK_SIZE;
|
||||||
|
pub use types::*;
|
||||||
|
|
||||||
|
#[derive(thiserror::Error, Debug)]
|
||||||
|
pub enum OodleError {
|
||||||
|
#[error("{0}")]
|
||||||
|
Oodle(String),
|
||||||
|
#[error(transparent)]
|
||||||
|
Library(#[from] libloading::Error),
|
||||||
|
}
|
||||||
|
|
||||||
|
type Result<T> = std::result::Result<T, OodleError>;
|
||||||
|
|
||||||
|
static LIB: OnceLock<Library> = OnceLock::new();
|
||||||
|
|
||||||
|
/// Initialize the global library handle that this module's
|
||||||
|
/// functions operate on.
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
///
|
||||||
|
/// The safety concerns as described by [`libloading::Library::new`] apply.
|
||||||
|
pub unsafe fn init<P: AsRef<OsStr>>(name: Option<P>) {
|
||||||
|
let lib = match name {
|
||||||
|
Some(name) => Library::with_name(name),
|
||||||
|
None => Library::new(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let lib = lib.expect("Failed to load library.");
|
||||||
|
if LIB.set(lib).is_err() {
|
||||||
|
panic!("Library was already initialized. Did you call `init` twice?");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get() -> Result<&'static Library> {
|
||||||
|
match LIB.get() {
|
||||||
|
Some(lib) => Ok(lib),
|
||||||
|
None => {
|
||||||
|
let err = OodleError::Oodle(String::from("Library has not been initialized, yet."));
|
||||||
|
Err(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn decompress<I>(
|
||||||
|
data: I,
|
||||||
|
fuzz_safe: OodleLZ_FuzzSafe,
|
||||||
|
check_crc: OodleLZ_CheckCRC,
|
||||||
|
) -> Result<Vec<u8>>
|
||||||
|
where
|
||||||
|
I: AsRef<[u8]>,
|
||||||
|
{
|
||||||
|
let lib = get()?;
|
||||||
|
lib.decompress(data, fuzz_safe, check_crc)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn compress<I>(data: I) -> Result<Vec<u8>>
|
||||||
|
where
|
||||||
|
I: AsRef<[u8]>,
|
||||||
|
{
|
||||||
|
let lib = get()?;
|
||||||
|
lib.compress(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_decode_buffer_size(raw_size: usize, corruption_possible: bool) -> Result<usize> {
|
||||||
|
let lib = get()?;
|
||||||
|
lib.get_decode_buffer_size(raw_size, corruption_possible)
|
||||||
|
}
|
|
@ -1,43 +1,52 @@
|
||||||
use std::ffi::OsStr;
|
use std::{ffi::OsStr, ptr};
|
||||||
use std::ops::Deref;
|
|
||||||
use std::ptr;
|
|
||||||
|
|
||||||
use color_eyre::eyre;
|
use libloading::Symbol;
|
||||||
use color_eyre::Result;
|
|
||||||
use libloading::{Library, Symbol};
|
|
||||||
|
|
||||||
pub mod types;
|
use super::Result;
|
||||||
use types::*;
|
use crate::{types::*, OodleError};
|
||||||
|
|
||||||
// Hardcoded chunk size of Bitsquid's bundle compression
|
// Hardcoded chunk size of Bitsquid's bundle compression
|
||||||
pub const CHUNK_SIZE: usize = 512 * 1024;
|
pub const CHUNK_SIZE: usize = 512 * 1024;
|
||||||
pub const COMPRESSOR: OodleLZ_Compressor = OodleLZ_Compressor::Kraken;
|
pub const COMPRESSOR: OodleLZ_Compressor = OodleLZ_Compressor::Kraken;
|
||||||
pub const LEVEL: OodleLZ_CompressionLevel = OodleLZ_CompressionLevel::Optimal2;
|
pub const LEVEL: OodleLZ_CompressionLevel = OodleLZ_CompressionLevel::Optimal2;
|
||||||
|
|
||||||
pub struct Oodle {
|
#[cfg(target_os = "windows")]
|
||||||
lib: Library,
|
const OODLE_LIB_NAME: &str = "oo2core_8_win64";
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
const OODLE_LIB_NAME: &str = "liboo2corelinux64.so";
|
||||||
|
|
||||||
|
pub struct Library {
|
||||||
|
inner: libloading::Library,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Oodle {
|
impl Library {
|
||||||
pub fn new<P>(lib: P) -> Result<Self>
|
/// Load the Oodle library by its default name.
|
||||||
where
|
///
|
||||||
P: AsRef<OsStr>,
|
/// The default name is platform-specific:
|
||||||
{
|
/// - Windows: `oo2core_8_win64`
|
||||||
let lib = unsafe { Library::new(lib)? };
|
/// - Linux: `liboo2corelinux64.so`
|
||||||
|
///
|
||||||
unsafe {
|
/// # Safety
|
||||||
let fun: Symbol<OodleCore_Plugins_SetPrintf> =
|
///
|
||||||
lib.get(b"OodleCore_Plugins_SetPrintf\0")?;
|
/// The safety concerns as described by [`libloading::Library::new`] apply.
|
||||||
let printf: Symbol<t_fp_OodleCore_Plugin_Printf> =
|
pub unsafe fn new() -> Result<Self> {
|
||||||
lib.get(b"OodleCore_Plugin_Printf_Verbose\0")?;
|
Self::with_name(OODLE_LIB_NAME)
|
||||||
|
|
||||||
fun(*printf.deref());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Self { lib })
|
/// Load the Oodle library by the given name or path.
|
||||||
|
///
|
||||||
|
/// See [`libloading::Library::new`] for how the `name` parameter is handled.
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
///
|
||||||
|
/// The safety concerns as described by [`libloading::Library::new`] apply.
|
||||||
|
pub unsafe fn with_name<P: AsRef<OsStr>>(name: P) -> Result<Self> {
|
||||||
|
let inner = libloading::Library::new(name)?;
|
||||||
|
Ok(Self { inner })
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument(name = "Oodle::decompress", skip(self, data))]
|
#[tracing::instrument(skip(self, data))]
|
||||||
pub fn decompress<I>(
|
pub fn decompress<I>(
|
||||||
&self,
|
&self,
|
||||||
data: I,
|
data: I,
|
||||||
|
@ -61,7 +70,7 @@ impl Oodle {
|
||||||
};
|
};
|
||||||
|
|
||||||
let ret = unsafe {
|
let ret = unsafe {
|
||||||
let decompress: Symbol<OodleLZ_Decompress> = self.lib.get(b"OodleLZ_Decompress\0")?;
|
let decompress: Symbol<OodleLZ_Decompress> = self.inner.get(b"OodleLZ_Decompress\0")?;
|
||||||
|
|
||||||
decompress(
|
decompress(
|
||||||
data.as_ptr() as *const _,
|
data.as_ptr() as *const _,
|
||||||
|
@ -82,7 +91,8 @@ impl Oodle {
|
||||||
};
|
};
|
||||||
|
|
||||||
if ret == 0 {
|
if ret == 0 {
|
||||||
eyre::bail!("Decompression failed.");
|
let err = OodleError::Oodle(String::from("Decompression failed."));
|
||||||
|
return Err(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(out)
|
Ok(out)
|
||||||
|
@ -100,7 +110,7 @@ impl Oodle {
|
||||||
let mut out = vec![0u8; CHUNK_SIZE];
|
let mut out = vec![0u8; CHUNK_SIZE];
|
||||||
|
|
||||||
let ret = unsafe {
|
let ret = unsafe {
|
||||||
let compress: Symbol<OodleLZ_Compress> = self.lib.get(b"OodleLZ_Compress\0")?;
|
let compress: Symbol<OodleLZ_Compress> = self.inner.get(b"OodleLZ_Compress\0")?;
|
||||||
|
|
||||||
compress(
|
compress(
|
||||||
COMPRESSOR,
|
COMPRESSOR,
|
||||||
|
@ -119,7 +129,8 @@ impl Oodle {
|
||||||
tracing::debug!(compressed_size = ret, "Compressed chunk");
|
tracing::debug!(compressed_size = ret, "Compressed chunk");
|
||||||
|
|
||||||
if ret == 0 {
|
if ret == 0 {
|
||||||
eyre::bail!("Compression failed.");
|
let err = OodleError::Oodle(String::from("Compression failed."));
|
||||||
|
return Err(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
out.resize(ret as usize, 0);
|
out.resize(ret as usize, 0);
|
||||||
|
@ -134,7 +145,7 @@ impl Oodle {
|
||||||
) -> Result<usize> {
|
) -> Result<usize> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let f: Symbol<OodleLZ_GetDecodeBufferSize> =
|
let f: Symbol<OodleLZ_GetDecodeBufferSize> =
|
||||||
self.lib.get(b"OodleLZ_GetDecodeBufferSize\0")?;
|
self.inner.get(b"OodleLZ_GetDecodeBufferSize\0")?;
|
||||||
|
|
||||||
let size = f(COMPRESSOR, raw_size, corruption_possible);
|
let size = f(COMPRESSOR, raw_size, corruption_possible);
|
||||||
Ok(size)
|
Ok(size)
|
|
@ -16,6 +16,7 @@ nanorand = "0.7.0"
|
||||||
pin-project-lite = "0.2.9"
|
pin-project-lite = "0.2.9"
|
||||||
serde = { version = "1.0.147", features = ["derive"] }
|
serde = { version = "1.0.147", features = ["derive"] }
|
||||||
serde_sjson = { path = "../../lib/serde_sjson", version = "*" }
|
serde_sjson = { path = "../../lib/serde_sjson", version = "*" }
|
||||||
|
oodle-sys = { path = "../../lib/oodle-sys", version = "*" }
|
||||||
tokio = { version = "1.21.2", features = ["rt-multi-thread", "fs", "process", "macros", "tracing", "io-util", "io-std"] }
|
tokio = { version = "1.21.2", features = ["rt-multi-thread", "fs", "process", "macros", "tracing", "io-util", "io-std"] }
|
||||||
tokio-stream = { version = "0.1.11", features = ["fs", "io-util"] }
|
tokio-stream = { version = "0.1.11", features = ["fs", "io-util"] }
|
||||||
tracing = { version = "0.1.37", features = ["async-await"] }
|
tracing = { version = "0.1.37", features = ["async-await"] }
|
||||||
|
|
|
@ -3,11 +3,10 @@ use std::path::Path;
|
||||||
|
|
||||||
use color_eyre::eyre::{self, Context, Result};
|
use color_eyre::eyre::{self, Context, Result};
|
||||||
use color_eyre::{Help, Report, SectionExt};
|
use color_eyre::{Help, Report, SectionExt};
|
||||||
|
use oodle_sys::{OodleLZ_CheckCRC, OodleLZ_FuzzSafe, CHUNK_SIZE};
|
||||||
|
|
||||||
use crate::binary::sync::*;
|
use crate::binary::sync::*;
|
||||||
use crate::murmur::{HashGroup, Murmur64};
|
use crate::murmur::{HashGroup, Murmur64};
|
||||||
use crate::oodle::types::{OodleLZ_CheckCRC, OodleLZ_FuzzSafe};
|
|
||||||
use crate::oodle::CHUNK_SIZE;
|
|
||||||
|
|
||||||
pub(crate) mod file;
|
pub(crate) mod file;
|
||||||
|
|
||||||
|
@ -198,9 +197,7 @@ impl Bundle {
|
||||||
decompressed.append(&mut compressed_buffer);
|
decompressed.append(&mut compressed_buffer);
|
||||||
} else {
|
} else {
|
||||||
// TODO: Optimize to not reallocate?
|
// TODO: Optimize to not reallocate?
|
||||||
let oodle_lib = ctx.oodle.as_ref().unwrap();
|
let mut raw_buffer = oodle_sys::decompress(
|
||||||
let mut raw_buffer = oodle_lib
|
|
||||||
.decompress(
|
|
||||||
&compressed_buffer,
|
&compressed_buffer,
|
||||||
OodleLZ_FuzzSafe::No,
|
OodleLZ_FuzzSafe::No,
|
||||||
OodleLZ_CheckCRC::No,
|
OodleLZ_CheckCRC::No,
|
||||||
|
@ -246,7 +243,7 @@ impl Bundle {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument(skip_all)]
|
#[tracing::instrument(skip_all)]
|
||||||
pub fn to_binary(&self, ctx: &crate::Context) -> Result<Vec<u8>> {
|
pub fn to_binary(&self) -> Result<Vec<u8>> {
|
||||||
let mut w = Cursor::new(Vec::new());
|
let mut w = Cursor::new(Vec::new());
|
||||||
w.write_u32(self.format.into())?;
|
w.write_u32(self.format.into())?;
|
||||||
// TODO: Find out what this is.
|
// TODO: Find out what this is.
|
||||||
|
@ -293,12 +290,10 @@ impl Bundle {
|
||||||
w.write_u32(0)?;
|
w.write_u32(0)?;
|
||||||
|
|
||||||
let chunks = unpacked_data.chunks(CHUNK_SIZE);
|
let chunks = unpacked_data.chunks(CHUNK_SIZE);
|
||||||
|
|
||||||
let oodle_lib = ctx.oodle.as_ref().expect("oodle library not defined");
|
|
||||||
let mut chunk_sizes = Vec::with_capacity(num_chunks);
|
let mut chunk_sizes = Vec::with_capacity(num_chunks);
|
||||||
|
|
||||||
for chunk in chunks {
|
for chunk in chunks {
|
||||||
let compressed = oodle_lib.compress(chunk)?;
|
let compressed = oodle_sys::compress(chunk)?;
|
||||||
tracing::trace!(
|
tracing::trace!(
|
||||||
raw_chunk_size = chunk.len(),
|
raw_chunk_size = chunk.len(),
|
||||||
compressed_chunk_size = compressed.len()
|
compressed_chunk_size = compressed.len()
|
||||||
|
@ -335,7 +330,7 @@ impl Bundle {
|
||||||
/// This is mainly useful for debugging purposes or
|
/// This is mainly useful for debugging purposes or
|
||||||
/// to manullay inspect the raw data.
|
/// to manullay inspect the raw data.
|
||||||
#[tracing::instrument(skip_all)]
|
#[tracing::instrument(skip_all)]
|
||||||
pub fn decompress<B>(ctx: &crate::Context, binary: B) -> Result<Vec<u8>>
|
pub fn decompress<B>(_ctx: &crate::Context, binary: B) -> Result<Vec<u8>>
|
||||||
where
|
where
|
||||||
B: AsRef<[u8]>,
|
B: AsRef<[u8]>,
|
||||||
{
|
{
|
||||||
|
@ -399,9 +394,8 @@ where
|
||||||
let mut compressed_buffer = vec![0u8; chunk_size];
|
let mut compressed_buffer = vec![0u8; chunk_size];
|
||||||
r.read_exact(&mut compressed_buffer)?;
|
r.read_exact(&mut compressed_buffer)?;
|
||||||
|
|
||||||
let oodle_lib = ctx.oodle.as_ref().unwrap();
|
|
||||||
// TODO: Optimize to not reallocate?
|
// TODO: Optimize to not reallocate?
|
||||||
let mut raw_buffer = oodle_lib.decompress(
|
let mut raw_buffer = oodle_sys::decompress(
|
||||||
&compressed_buffer,
|
&compressed_buffer,
|
||||||
OodleLZ_FuzzSafe::No,
|
OodleLZ_FuzzSafe::No,
|
||||||
OodleLZ_CheckCRC::No,
|
OodleLZ_CheckCRC::No,
|
||||||
|
|
|
@ -1,11 +1,9 @@
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use crate::murmur::{Dictionary, HashGroup, Murmur32, Murmur64};
|
use crate::murmur::{Dictionary, HashGroup, Murmur32, Murmur64};
|
||||||
use crate::oodle::Oodle;
|
|
||||||
|
|
||||||
pub struct Context {
|
pub struct Context {
|
||||||
pub lookup: Dictionary,
|
pub lookup: Dictionary,
|
||||||
pub oodle: Option<Oodle>,
|
|
||||||
pub ljd: Option<String>,
|
pub ljd: Option<String>,
|
||||||
pub revorb: Option<String>,
|
pub revorb: Option<String>,
|
||||||
pub ww2ogg: Option<String>,
|
pub ww2ogg: Option<String>,
|
||||||
|
@ -16,7 +14,6 @@ impl Context {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
lookup: Dictionary::new(),
|
lookup: Dictionary::new(),
|
||||||
oodle: None,
|
|
||||||
ljd: None,
|
ljd: None,
|
||||||
revorb: None,
|
revorb: None,
|
||||||
ww2ogg: None,
|
ww2ogg: None,
|
||||||
|
|
|
@ -84,8 +84,8 @@ type PackageDefinition = HashMap<String, HashSet<String>>;
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct Package {
|
pub struct Package {
|
||||||
name: String,
|
_name: String,
|
||||||
root: PathBuf,
|
_root: PathBuf,
|
||||||
inner: PackageType,
|
inner: PackageType,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,8 +159,8 @@ impl Package {
|
||||||
|
|
||||||
let pkg = Self {
|
let pkg = Self {
|
||||||
inner,
|
inner,
|
||||||
name,
|
_name: name,
|
||||||
root: root.to_path_buf(),
|
_root: root.to_path_buf(),
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(pkg)
|
Ok(pkg)
|
||||||
|
@ -206,8 +206,8 @@ impl Package {
|
||||||
|
|
||||||
let pkg = Self {
|
let pkg = Self {
|
||||||
inner,
|
inner,
|
||||||
name,
|
_name: name,
|
||||||
root: PathBuf::new(),
|
_root: PathBuf::new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(pkg)
|
Ok(pkg)
|
||||||
|
|
|
@ -1,13 +1,9 @@
|
||||||
#![feature(c_size_t)]
|
|
||||||
|
|
||||||
mod binary;
|
mod binary;
|
||||||
mod bundle;
|
mod bundle;
|
||||||
mod context;
|
mod context;
|
||||||
pub mod filetype;
|
pub mod filetype;
|
||||||
pub mod murmur;
|
pub mod murmur;
|
||||||
mod oodle;
|
|
||||||
|
|
||||||
pub use bundle::decompress;
|
pub use bundle::decompress;
|
||||||
pub use bundle::{Bundle, BundleFile, BundleFileType};
|
pub use bundle::{Bundle, BundleFile, BundleFileType};
|
||||||
pub use context::Context;
|
pub use context::Context;
|
||||||
pub use oodle::Oodle;
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue