extract_modules/
extract_modules.rs

1use std::{
2    fs::{File, create_dir_all},
3    io::{BufWriter, Read, Seek, Write},
4    path::{Path, PathBuf},
5};
6
7use argh::FromArgs;
8use infinite_rs::{ModuleFile, Result};
9
10#[derive(FromArgs, Debug)]
11/// Tool that extracts files from modules of any version from Halo Infinite
12struct InfiniteExtract {
13    /// path to where modules are stored (deploy folder)
14    #[argh(option)]
15    deploy_path: PathBuf,
16    /// path to folder to output files to.
17    #[argh(option)]
18    output_path: PathBuf,
19}
20
21fn load_modules<R: AsRef<Path>>(deploy_path: R) -> Result<Vec<ModuleFile>> {
22    let mut modules = Vec::new();
23    for entry in walkdir::WalkDir::new(deploy_path)
24        .into_iter()
25        .filter_map(|e| e.ok())
26    {
27        if entry.file_type().is_file() {
28            let file_path = entry.path().to_str().unwrap();
29            if file_path.ends_with(".module") {
30                let module = ModuleFile::from_path(file_path)?;
31                modules.push(module);
32            }
33        }
34    }
35    Ok(modules)
36}
37
38fn main() -> Result<()> {
39    let args: InfiniteExtract = argh::from_env();
40    let mut modules = load_modules(args.deploy_path)?;
41    for module in &mut modules {
42        for idx in 0..module.files.len() {
43            module.read_tag(idx as u32)?;
44        }
45
46        for file in &mut module.files {
47            let mut buffer = Vec::with_capacity(file.total_uncompressed_size as usize);
48            if let Some(stream) = file.data_stream.as_mut() {
49                stream.rewind()?;
50                stream.read_to_end(&mut buffer)?;
51            }
52            let tag_path = file
53                .tag_name
54                .replace(" ", "_")
55                .replace("*", "_")
56                .replace(r"\", "/")
57                .replace(":", "_");
58            let path = PathBuf::from(&args.output_path).join(tag_path);
59            create_dir_all(path.parent().unwrap())?;
60            let filee = File::create(path)?;
61            let mut bw = BufWriter::new(&filee);
62            bw.write_all(&buffer)?;
63        }
64    }
65    Ok(())
66}