diff options
Diffstat (limited to 'packer')
-rw-r--r-- | packer/Cargo.toml | 9 | ||||
-rw-r--r-- | packer/README.md | 0 | ||||
-rw-r--r-- | packer/src/main.rs | 170 |
3 files changed, 179 insertions, 0 deletions
diff --git a/packer/Cargo.toml b/packer/Cargo.toml new file mode 100644 index 0000000..cbf418c --- /dev/null +++ b/packer/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "packer" +version = "0.1.0" +edition = "2021" + +[dependencies] +byteorder = "1.4.3" +serde = { version = "1.0.160", features = ["derive"] } +serde_json = "1.0.96" diff --git a/packer/README.md b/packer/README.md new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/packer/README.md diff --git a/packer/src/main.rs b/packer/src/main.rs new file mode 100644 index 0000000..ae4e02a --- /dev/null +++ b/packer/src/main.rs @@ -0,0 +1,170 @@ +use std::env; +use std::{ + fs::{self, File}, + io::{BufReader, Read}, +}; + +use byteorder::{ByteOrder, LittleEndian}; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug)] +pub struct ImportListElement { + pub extension: String, + pub index: u32, + pub name: String, + pub unknown0: u32, + pub unknown1: u32, + pub unknown2: u32, +} + +#[derive(Debug)] +pub struct ListElement { + pub extension: String, + pub index: u32, + pub name: String, + pub position: u32, + pub size: u32, + pub unknown0: u32, + pub unknown1: u32, + pub unknown2: u32, +} + +fn main() { + let args: Vec<String> = env::args().collect(); + + let input = &args[1]; + let output = &args[2]; + + pack(String::from(input), String::from(output)); +} + +fn pack(input: String, output: String) { + // Загружаем индекс-файл + let index_file = format!("{}/{}", input, "index.json"); + let data = fs::read_to_string(index_file).unwrap(); + let list: Vec<ImportListElement> = serde_json::from_str(&data).unwrap(); + + // Общий буфер хранения файлов + let mut content_buffer: Vec<u8> = Vec::new(); + let mut list_buffer: Vec<u8> = Vec::new(); + + // Общее количество файлов + let total_files: u32 = list.len() as u32; + + for (index, item) in list.iter().enumerate() { + // Открываем дескриптор файла + let path = format!("{}/{}", input, item.name); + let file = File::open(path).unwrap(); + let metadata = file.metadata().unwrap(); + + // Считываем файл в буфер + let mut reader = BufReader::new(file); + let mut file_buffer: Vec<u8> = Vec::new(); + reader.read_to_end(&mut file_buffer).unwrap(); + + // Выравнивание буфера + if index != 0 { + while content_buffer.len() % 8 != 0 { + content_buffer.push(0); + } + } + + // Получение позиции файла + let position = content_buffer.len() + 16; + + // Записываем файл в буфер + content_buffer.extend(file_buffer); + + // Формируем элемент + let element = ListElement { + extension: item.extension.to_string(), + index: item.index, + name: item.name.to_string(), + position: position as u32, + size: metadata.len() as u32, + unknown0: item.unknown0, + unknown1: item.unknown1, + unknown2: item.unknown2, + }; + + // Создаем буфер из элемента + let mut element_buffer: Vec<u8> = Vec::new(); + + // Пишем тип файла + let mut extension_buffer: [u8; 4] = [0; 4]; + let mut file_extension_buffer = element.extension.into_bytes(); + file_extension_buffer.resize(4, 0); + extension_buffer.copy_from_slice(&file_extension_buffer); + element_buffer.extend(extension_buffer); + + // Пишем неизвестное значение #1 + let mut unknown0_buffer: [u8; 4] = [0; 4]; + LittleEndian::write_u32(&mut unknown0_buffer, element.unknown0); + element_buffer.extend(unknown0_buffer); + + // Пишем неизвестное значение #2 + let mut unknown1_buffer: [u8; 4] = [0; 4]; + LittleEndian::write_u32(&mut unknown1_buffer, element.unknown1); + element_buffer.extend(unknown1_buffer); + + // Пишем размер файла + let mut file_size_buffer: [u8; 4] = [0; 4]; + LittleEndian::write_u32(&mut file_size_buffer, element.size); + element_buffer.extend(file_size_buffer); + + // Пишем неизвестное значение #3 + let mut unknown2_buffer: [u8; 4] = [0; 4]; + LittleEndian::write_u32(&mut unknown2_buffer, element.unknown2); + element_buffer.extend(unknown2_buffer); + + // Пишем название файла + let mut name_buffer: [u8; 36] = [0; 36]; + let mut file_name_buffer = element.name.into_bytes(); + file_name_buffer.resize(36, 0); + name_buffer.copy_from_slice(&file_name_buffer); + element_buffer.extend(name_buffer); + + // Пишем позицию файла + let mut position_buffer: [u8; 4] = [0; 4]; + LittleEndian::write_u32(&mut position_buffer, element.position); + element_buffer.extend(position_buffer); + + // Пишем индекс файла + let mut index_buffer: [u8; 4] = [0; 4]; + LittleEndian::write_u32(&mut index_buffer, element.index); + element_buffer.extend(index_buffer); + + // Добавляем итоговый буфер в буфер элементов списка + list_buffer.extend(element_buffer); + } + + let mut header_buffer: Vec<u8> = Vec::new(); + + // Пишем первый тип файла + let mut header_type_1 = [0; 4]; + LittleEndian::write_u32(&mut header_type_1, 1936020046_u32); + header_buffer.extend(header_type_1); + + // Пишем второй тип файла + let mut header_type_2 = [0; 4]; + LittleEndian::write_u32(&mut header_type_2, 256_u32); + header_buffer.extend(header_type_2); + + // Пишем количество файлов + let mut header_total_files = [0; 4]; + LittleEndian::write_u32(&mut header_total_files, total_files); + header_buffer.extend(header_total_files); + + // Пишем общий размер файла + let mut header_total_size = [0; 4]; + let total_size: u32 = ((content_buffer.len() + 16) as u32) + (total_files * 64); + LittleEndian::write_u32(&mut header_total_size, total_size); + header_buffer.extend(header_total_size); + + let mut result_buffer: Vec<u8> = Vec::new(); + result_buffer.extend(header_buffer); + result_buffer.extend(content_buffer); + result_buffer.extend(list_buffer); + + fs::write(output, result_buffer).unwrap(); +} |