pub struct ModuleFileEntry {Show 27 fields
unknown: u8,
pub flags: FileEntryFlags,
block_count: u16,
block_index: i32,
pub resource_index: i32,
pub tag_group: String,
data_offset: u64,
pub data_offset_flags: DataOffsetType,
pub total_compressed_size: u32,
pub total_uncompressed_size: u32,
pub tag_id: i32,
pub uncompressed_header_size: u32,
pub uncompressed_tag_data_size: u32,
pub uncompressed_resource_data_size: u32,
pub uncompressed_actual_resource_size: u32,
header_alignment: u8,
tag_data_alignment: u8,
resource_data_alignment: u8,
actual_resource_data_alignment: u8,
pub(crate) name_offset: u32,
pub parent_index: i32,
pub asset_hash: i128,
pub resource_count: i32,
pub data_stream: Option<BufReader<Cursor<Vec<u8>>>>,
pub tag_info: Option<TagFile>,
pub is_loaded: bool,
pub tag_name: String,
}
Expand description
Module file entry structure containing metadata relating to file and required buffer sizes and offsets for the decompressor, as well as global tag ID, resource references and class.
Fields§
§unknown: u8
Unknown, some sort of size?
flags: FileEntryFlags
Determine how the file should be read.
block_count: u16
Number of blocks that make up the file.
block_index: i32
Index of the first block in the module.
resource_index: i32
Index of the first resource in the module’s resource list.
tag_group: String
4 byte-long string for tag group, stored as big endian. This determines how the rest of the tag is read. Example:
bitm
: Bitmapmat
: Material
data_offset: u64
Offset of compressed/uncompressed data in from the start of compressed data in the module.
data_offset_flags: DataOffsetType
Where the offset is located.
total_compressed_size: u32
Size in bytes of compressed buffer in module.
total_uncompressed_size: u32
Size in bytes of buffer to decompress into.
tag_id: i32
MurmurHash3_x86_64
32 bit hash of tag path.
Referred to in-memory as “global tag id”
Is set to -1 if file is resource.
uncompressed_header_size: u32
Size in bytes of header in decompressed buffer.
uncompressed_tag_data_size: u32
Size in bytes of actual tag data in decompressed buffer.
uncompressed_resource_data_size: u32
Size in bytes of resource data in decompressed buffer.
uncompressed_actual_resource_size: u32
Size in bytes of “external” resource data in decompressed buffer. (for instance, havok data or bitmaps)
header_alignment: u8
Power of 2 to align the header buffer to (ex w. 4 = align to a multiple of 16 bytes).
tag_data_alignment: u8
Power of 2 to align the tag data buffer to.
resource_data_alignment: u8
Power of 2 to align the resource data buffer to.
actual_resource_data_alignment: u8
Power of 2 to align the actual resource data buffer to.
name_offset: u32
Offset where the name of the file is located in the string table.
This is not read after ModuleVersion::Season3
.
parent_index: i32
Used with resources to point back to the parent file. -1 = none
asset_hash: i128
Murmur3_x64_128
hash of (what appears to be) the original file that this file was built from.
This is not always the same thing as the file stored in the module.
Only verified if the HasBlocks
flag is not set.
resource_count: i32
Number of resources owned by the file.
data_stream: Option<BufReader<Cursor<Vec<u8>>>>
Data stream containing a buffer of bytes to read/seek.
tag_info: Option<TagFile>
The actual tag file read from the contents (including header), only valid if file is not a resource.
is_loaded: bool
Indicates if file is cached (has data stream) or not.
tag_name: String
Name of the tag as specified in the module string list. Set to tag id if module version does not support names.
Implementations§
Source§impl ModuleFileEntry
impl ModuleFileEntry
Sourcepub fn read<R: BufReaderExt>(
&mut self,
reader: &mut R,
module_version: &ModuleVersion,
) -> Result<()>
pub fn read<R: BufReaderExt>( &mut self, reader: &mut R, module_version: &ModuleVersion, ) -> Result<()>
Reads module file entry data from a reader based on the module version.
§Arguments
reader
- A mutable reference to a reader implementingBufReaderExt
module_version
- Version of the module being read
§Errors
- If the reader fails to read the structure
ReadError
Sourcefn read_flight1<R: BufReaderExt>(&mut self, reader: &mut R) -> Result<()>
fn read_flight1<R: BufReaderExt>(&mut self, reader: &mut R) -> Result<()>
Reads module file entry data specifically for modules of version Flight1
.
Sourcefn read_other<R: BufReaderExt>(&mut self, reader: &mut R) -> Result<()>
fn read_other<R: BufReaderExt>(&mut self, reader: &mut R) -> Result<()>
Reads module file entry data for non-Flight1
module versions.
Sourcepub(super) fn read_tag(
&mut self,
reader: &mut BufReader<File>,
data_offset: u64,
blocks: &[ModuleBlockEntry],
module_version: &ModuleVersion,
uses_hd1: bool,
) -> Result<()>
pub(super) fn read_tag( &mut self, reader: &mut BufReader<File>, data_offset: u64, blocks: &[ModuleBlockEntry], module_version: &ModuleVersion, uses_hd1: bool, ) -> Result<()>
Reads and loads tag data from a file.
§Arguments
reader
- A mutable reference to aBufReader<File>
from which to read the data.data_offset
- Starting offset in bytes of the data in the file.blocks
- Metadata for data blocks.module_version
- Version of the module being read
§Errors
Sourcefn read_multiple_blocks(
&self,
reader: &mut BufReader<File>,
blocks: &[ModuleBlockEntry],
file_offset: u64,
data: &mut [u8],
) -> Result<()>
fn read_multiple_blocks( &self, reader: &mut BufReader<File>, blocks: &[ModuleBlockEntry], file_offset: u64, data: &mut [u8], ) -> Result<()>
Reads multiple blocks of data from the file.
This function reads multiple blocks of data, which can be either compressed or uncompressed, from the file and stores them in the provided data buffer.
§Arguments
reader
- A mutable reference to aBufReader<File>
from which to read the data.blocks
- A slice ofModuleBlockEntry
containing metadata about each block.file_offset
- The offset in the file where the data blocks start.data
- A mutable slice where the (decompressed) data will be stored.
§Errors
- If the reader fails to read the exact number of bytes
ReadError
- If the block index is negative
ModuleError::NegativeBlockIndex
§Safety
- This function has an unsafe component because it can call the
read_compressed_block
function, which usesdecompress
which is unsafe.
Sourcepub fn read_metadata<T: Default + TagStructure>(
&mut self,
struct_type: &mut T,
) -> Result<T>
pub fn read_metadata<T: Default + TagStructure>( &mut self, struct_type: &mut T, ) -> Result<T>
Reads a specified structure implementing TagStructure
from the tag data.
This function exhausts the inner data_stream
buffer to read the contents of the specified
struct. It first looks for the main struct definition of the file, then gets the referenced
data block and creates a reader for it. The initial contents of the struct are read, and
field block definitions are loaded recursively.
§Arguments
struct_type
- A mutable reference to the struct implementingTagStructure
to read the data into.
§Errors
- If the tag data is not loaded
TagError::NotLoaded
- If the tag info is not present
TagError::NoTagInfo
- If the main struct definition is not found
TagError::MainStructNotFound
- If the reader fails to read the exact number of bytes
ReadError
Examples found in repository?
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
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}