Struct ModuleFile

Source
pub struct ModuleFile {
    pub header: ModuleHeader,
    pub files: Vec<ModuleFileEntry>,
    pub resource_indices: Vec<u32>,
    blocks: Vec<ModuleBlockEntry>,
    file_data_offset: u64,
    module_file: Option<BufReader<File>>,
    hd1_file: Option<BufReader<File>>,
    pub use_hd1: bool,
}
Expand description

Module structure which contains the layout of the entire module file.

Fields§

§header: ModuleHeader

Information relating to how the other fields should be read.

§files: Vec<ModuleFileEntry>

Metadata regarding compression and layout of files (tags).

§resource_indices: Vec<u32>

Indices of resource files present in the module.

§blocks: Vec<ModuleBlockEntry>

Uncompressed/compressed blocks making up a file.

§file_data_offset: u64

Offset in BufReader where file data starts.

§module_file: Option<BufReader<File>>

Reference to the module file buffer.

§hd1_file: Option<BufReader<File>>

Reference to HD1 buffer if it exists.

§use_hd1: bool

Whether to use the HD1 module or not.

Implementations§

Source§

impl ModuleFile

Source

pub fn from_path<T: AsRef<Path>>(file_path: T) -> Result<Self>

Instantiates a ModuleFile object from the given file path.

Examples found in repository?
examples/extract_modules.rs (line 30)
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}
More examples
Hide additional examples
examples/load_all_modules.rs (line 20)
11fn load_modules<R: AsRef<Path>>(deploy_path: R) -> Result<Vec<ModuleFile>> {
12    let mut modules = Vec::new();
13    for entry in walkdir::WalkDir::new(deploy_path)
14        .into_iter()
15        .filter_map(|e| e.ok())
16    {
17        if entry.file_type().is_file() {
18            let file_path = entry.path().to_str().unwrap();
19            if file_path.ends_with(".module") {
20                let module = ModuleFile::from_path(file_path)?;
21                modules.push(module);
22            }
23        }
24    }
25    Ok(modules)
26}
examples/load_scripts.rs (line 24)
23fn main() -> Result<()> {
24    let mut module = ModuleFile::from_path(DEPLOY_PATH)?;
25    for idx in 0..module.files.len() {
26        if module.files[idx].tag_group == SCRIPT_GROUP {
27            let tag = module.read_tag(idx as u32)?;
28            if let Some(tag) = tag {
29                let mut source = HsSourceFileTag::default();
30                tag.read_metadata(&mut source)?;
31
32                let server_buf = source.server.data;
33                let client_buf = source.client.data;
34
35                let server_file = File::create(format!("{SAVE_PATH}/{}_server.luac", tag.tag_id))?;
36                let mut bw = BufWriter::new(server_file);
37                bw.write_all(&server_buf)?;
38
39                let client_file = File::create(format!("{SAVE_PATH}/{}_client.luac", tag.tag_id))?;
40                let mut bw = BufWriter::new(client_file);
41                bw.write_all(&client_buf)?;
42            }
43        }
44    }
45    Ok(())
46}
Source

pub fn read<T: AsRef<Path>>(&mut self, file_path: T) -> Result<()>

Reads the module file from the given file path. This function reads the entire structure of the module file. It also calculates and stores important offsets within the file.

§Arguments
  • file_path - A reference to a type that implements Path that holds the path to the module file.
§Errors
Source

fn open_hd1<T: AsRef<Path>>(&mut self, file_path: T) -> Result<()>

Opens the HD1 file if it exists.

Source

fn get_tag_path(&self, index: usize, depth: usize) -> Result<String>

Gets the tag path of a file entry.

This function returns the tag path of a file entry based on the provided index. For file entries that have a parent, the function recursively gets the tag path of the parent and appends the child index to the path.

§Arguments
  • index - The index of the file entry to get the tag path from.
  • depth - The depth of the recursion. This is used to prevent infinite recursion.
§Returns

Returns the tag path of the file entry if the operation is successful.

Source

pub fn read_tag(&mut self, index: u32) -> Result<Option<&mut ModuleFileEntry>>

Reads a specific tag from the module file.

This function reads a specific tag from the module file based on the provided index. It also utilizes the HD1 stream if the file entry has the flag set for it and the stream is loaded, and returns None if the tag offset is invalid.

§Arguments
  • index - The index of the file entry to read the tag from. This index corresponds to the position of the file entry in the files vector.
§Returns

Returns a mutable reference to the file if the read operation is successful, or an Error, a None if the file was not read (if tag offset is specified as invalid) or the containing the I/O error if any reading operation fails.

Examples found in repository?
examples/load_all_modules.rs (line 153)
148fn main() -> Result<()> {
149    let mut modules = load_modules(String::from("C:/XboxGames/Halo Infinite/Content/deploy/"))?;
150
151    for module in &mut modules {
152        for index in 0..module.files.len() {
153            let tag = module.read_tag(index as u32)?;
154            if let Some(tag) = tag {
155                if tag.tag_group == "mat " {
156                    let mut mat = MaterialTag::default();
157                    tag.read_metadata(&mut mat)?;
158                }
159                // explicitly drop buffer to free up memory
160                // normally, can take 50+ GBs of RAM
161                module.files[index].data_stream = None
162            }
163        }
164    }
165    Ok(())
166}
More examples
Hide additional examples
examples/load_scripts.rs (line 27)
23fn main() -> Result<()> {
24    let mut module = ModuleFile::from_path(DEPLOY_PATH)?;
25    for idx in 0..module.files.len() {
26        if module.files[idx].tag_group == SCRIPT_GROUP {
27            let tag = module.read_tag(idx as u32)?;
28            if let Some(tag) = tag {
29                let mut source = HsSourceFileTag::default();
30                tag.read_metadata(&mut source)?;
31
32                let server_buf = source.server.data;
33                let client_buf = source.client.data;
34
35                let server_file = File::create(format!("{SAVE_PATH}/{}_server.luac", tag.tag_id))?;
36                let mut bw = BufWriter::new(server_file);
37                bw.write_all(&server_buf)?;
38
39                let client_file = File::create(format!("{SAVE_PATH}/{}_client.luac", tag.tag_id))?;
40                let mut bw = BufWriter::new(client_file);
41                bw.write_all(&client_buf)?;
42            }
43        }
44    }
45    Ok(())
46}
examples/extract_modules.rs (line 43)
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}
Source

pub fn read_tag_from_id( &mut self, global_id: i32, ) -> Result<Option<&mut ModuleFileEntry>>

Searches for the index of the tag given the global_id.

This function searches for the index of a tag in the files vector using the provided global_id. If the tag is found, it reads the tag using the read_tag function and stores it in the index.

§Arguments
  • global_id - The global tag ID of the file to find. This ID is used to identify the specific tag within the module file.
§Returns

Returns a mutable reference to the file if successful. If the tag is not found or couldn’t be read, it returns None. Any I/O error encountered during the operation is also returned if it occurs.

Trait Implementations§

Source§

impl Debug for ModuleFile

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for ModuleFile

Source§

fn default() -> ModuleFile

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.