aboutsummaryrefslogtreecommitdiff
path: root/packer/src/main.rs
blob: a5526e35166a70fc3f8e0b03f50289e0030096df (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
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, item.index);
        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);
    }

    // Выравнивание буфера
    while content_buffer.len() % 8 != 0 {
        content_buffer.push(0);
    }

    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();
}