load_all_modules/
load_all_modules.rs

1use std::path::Path;
2
3use bitflags::bitflags;
4use infinite_rs::tag::types::common_types::{
5    AnyTag, FieldBlock, FieldByteFlags, FieldCharEnum, FieldLongEnum, FieldReference, FieldStringId,
6};
7use infinite_rs::{ModuleFile, Result};
8use infinite_rs_derive::TagStructure;
9use num_enum::TryFromPrimitive;
10
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}
27
28#[derive(Default, Debug, TagStructure)]
29#[data(size(0x30))]
30struct MaterialShaderFunctionParameter {
31    #[data(offset(0x04))]
32    input_name: FieldStringId,
33}
34
35bitflags! {
36    #[derive(Default, Debug)]
37    pub struct MaterialFlags : u8 {
38        const CONVERTED_FROM_SHADER = 0b01;
39        const DECAL_POST_LIGHTING = 0b10;
40        const RUNTIME_GENERATED = 0b100;
41    }
42}
43
44#[derive(TryFromPrimitive, Debug, Default)]
45#[repr(u32)]
46enum MaterialParameterType {
47    #[default]
48    Bitmap,
49    Real,
50    Int,
51    Bool,
52    Color,
53    ScalarGPUProperty,
54    ColorGPUProperty,
55    String,
56    Preset,
57}
58
59#[derive(Default, Debug, TagStructure)]
60#[data(size(0x9c))]
61struct MaterialParameter {
62    #[data(offset(0x8))]
63    bitmap: FieldReference,
64    #[data(offset(0x4))]
65    parameter_type: FieldLongEnum<MaterialParameterType>,
66    #[data(offset(0x80))]
67    function_parameters: FieldBlock<MaterialShaderFunctionParameter>,
68}
69
70#[derive(Default, Debug, TagStructure)]
71#[data(size(0x38))]
72struct MaterialPostprocessTexture {
73    #[data(offset(0x00))]
74    texture: FieldReference,
75}
76
77#[derive(Default, Debug, TagStructure)]
78#[data(size(0xA0))]
79struct PostProcessDefinition {
80    #[data(offset(0x00))]
81    textures: FieldBlock<MaterialPostprocessTexture>,
82}
83
84#[derive(TryFromPrimitive, Debug, Default)]
85#[repr(u8)]
86enum MaterialStyleShaderSupportedLayers {
87    #[default]
88    Supports1Layer,
89    Supports4Layers,
90    Supports7Layers,
91    LayerShaderDisabled,
92}
93
94#[derive(TryFromPrimitive, Debug, Default)]
95#[repr(u8)]
96enum MaterialStyleShaderSupportsDamageEnum {
97    #[default]
98    No,
99    Yes,
100}
101
102#[derive(Default, Debug, TagStructure)]
103#[data(size(0x5c))]
104struct MaterialStyleInfo {
105    #[data(offset(0x00))]
106    material_style: FieldReference,
107    #[data(offset(0x1C))]
108    material_style_tag: FieldReference,
109    #[data(offset(0x38))]
110    region_name: FieldStringId,
111    #[data(offset(0x3C))]
112    base_intention: FieldStringId,
113    #[data(offset(0x40))]
114    mask0_red_channel_intention: FieldStringId,
115    #[data(offset(0x44))]
116    mask0_green_channel_intention: FieldStringId,
117    #[data(offset(0x48))]
118    mask0_blue_channel_intention: FieldStringId,
119    #[data(offset(0x4C))]
120    mask1_red_channel_intention: FieldStringId,
121    #[data(offset(0x50))]
122    mask1_green_channel_intention: FieldStringId,
123    #[data(offset(0x54))]
124    mask1_blue_channel_intention: FieldStringId,
125    #[data(offset(0x58))]
126    supported_layers: FieldCharEnum<MaterialStyleShaderSupportedLayers>,
127    #[data(offset(0x59))]
128    requires_damage: FieldCharEnum<MaterialStyleShaderSupportsDamageEnum>,
129}
130
131#[derive(Default, Debug, TagStructure)]
132#[data(size(0x88))]
133struct MaterialTag {
134    #[data(offset(0x00))]
135    any_tag: AnyTag,
136    #[data(offset(0x10))]
137    material_shader: FieldReference,
138    #[data(offset(0x2C))]
139    material_parameters: FieldBlock<MaterialParameter>,
140    #[data(offset(0x40))]
141    postprocess_definition: FieldBlock<PostProcessDefinition>,
142    #[data(offset(0x6A))]
143    flags: FieldByteFlags<MaterialFlags>,
144    #[data(offset(0x74))]
145    style_info: FieldBlock<MaterialStyleInfo>,
146}
147
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}