From afe6b9a29b1f4b5f116a96fa42ee929e32e530e3 Mon Sep 17 00:00:00 2001 From: Valentin Popov Date: Thu, 5 Feb 2026 00:37:59 +0400 Subject: feat: remove Rust project --- tools/nres-cli/Cargo.toml | 14 --- tools/nres-cli/README.md | 6 -- tools/nres-cli/src/main.rs | 198 -------------------------------------- tools/texture-decoder/Cargo.toml | 8 -- tools/texture-decoder/README.md | 13 --- tools/texture-decoder/src/main.rs | 41 -------- tools/unpacker/Cargo.toml | 9 -- tools/unpacker/README.md | 41 -------- tools/unpacker/src/main.rs | 124 ------------------------ 9 files changed, 454 deletions(-) delete mode 100644 tools/nres-cli/Cargo.toml delete mode 100644 tools/nres-cli/README.md delete mode 100644 tools/nres-cli/src/main.rs delete mode 100644 tools/texture-decoder/Cargo.toml delete mode 100644 tools/texture-decoder/README.md delete mode 100644 tools/texture-decoder/src/main.rs delete mode 100644 tools/unpacker/Cargo.toml delete mode 100644 tools/unpacker/README.md delete mode 100644 tools/unpacker/src/main.rs (limited to 'tools') diff --git a/tools/nres-cli/Cargo.toml b/tools/nres-cli/Cargo.toml deleted file mode 100644 index f2eedd0..0000000 --- a/tools/nres-cli/Cargo.toml +++ /dev/null @@ -1,14 +0,0 @@ -[package] -name = "nres-cli" -version = "0.2.3" -edition = "2021" - -[dependencies] -byteorder = "1.4" -clap = { version = "4.2", features = ["derive"] } -console = "0.16" -dialoguer = { version = "0.12", features = ["completion"] } -indicatif = "0.18" -libnres = { version = "0.1", path = "../../libs/nres" } -miette = { version = "7.0", features = ["fancy"] } -tempdir = "0.3" diff --git a/tools/nres-cli/README.md b/tools/nres-cli/README.md deleted file mode 100644 index fee1420..0000000 --- a/tools/nres-cli/README.md +++ /dev/null @@ -1,6 +0,0 @@ -# Console tool for NRes files (Deprecated) - -## Commands - -- `extract` - Extract game resources from a "NRes" file. -- `ls` - Get a list of files in a "NRes" file. \ No newline at end of file diff --git a/tools/nres-cli/src/main.rs b/tools/nres-cli/src/main.rs deleted file mode 100644 index 85086cb..0000000 --- a/tools/nres-cli/src/main.rs +++ /dev/null @@ -1,198 +0,0 @@ -extern crate core; -extern crate libnres; - -use std::io::Write; - -use clap::{Parser, Subcommand}; -use miette::{IntoDiagnostic, Result}; - -#[derive(Parser, Debug)] -#[command(name = "NRes CLI")] -#[command(about, author, version, long_about = None)] -struct Cli { - #[command(subcommand)] - command: Commands, -} - -#[derive(Subcommand, Debug)] -enum Commands { - /// Check if the "NRes" file can be extract - Check { - /// "NRes" file - file: String, - }, - /// Print debugging information on the "NRes" file - #[command(arg_required_else_help = true)] - Debug { - /// "NRes" file - file: String, - /// Filter results by file name - #[arg(long)] - name: Option, - }, - /// Extract files or a file from the "NRes" file - #[command(arg_required_else_help = true)] - Extract { - /// "NRes" file - file: String, - /// Overwrite files - #[arg(short, long, default_value_t = false, value_name = "TRUE|FALSE")] - force: bool, - /// Outbound directory - #[arg(short, long, value_name = "DIR")] - out: String, - }, - /// Print a list of files in the "NRes" file - #[command(arg_required_else_help = true)] - Ls { - /// "NRes" file - file: String, - }, -} - -pub fn main() -> Result<()> { - let stdout = console::Term::stdout(); - let cli = Cli::parse(); - - match cli.command { - Commands::Check { file } => command_check(stdout, file)?, - Commands::Debug { file, name } => command_debug(stdout, file, name)?, - Commands::Extract { file, force, out } => command_extract(stdout, file, out, force)?, - Commands::Ls { file } => command_ls(stdout, file)?, - } - - Ok(()) -} - -fn command_check(_stdout: console::Term, file: String) -> Result<()> { - let file = std::fs::File::open(file).into_diagnostic()?; - let list = libnres::reader::get_list(&file).into_diagnostic()?; - let tmp = tempdir::TempDir::new("nres").into_diagnostic()?; - let bar = indicatif::ProgressBar::new(list.len() as u64); - - bar.set_style(get_bar_style()?); - - for element in list { - bar.set_message(element.get_filename()); - - let path = tmp.path().join(element.get_filename()); - let mut output = std::fs::File::create(path).into_diagnostic()?; - let mut buffer = libnres::reader::get_file(&file, &element).into_diagnostic()?; - - output.write_all(&buffer).into_diagnostic()?; - buffer.clear(); - bar.inc(1); - } - - bar.finish(); - - Ok(()) -} - -fn command_debug(stdout: console::Term, file: String, name: Option) -> Result<()> { - let file = std::fs::File::open(file).into_diagnostic()?; - let mut list = libnres::reader::get_list(&file).into_diagnostic()?; - - let mut total_files_size: u32 = 0; - let mut total_files_gap: u32 = 0; - let mut total_files: u32 = 0; - - for (index, item) in list.iter().enumerate() { - total_files_size += item.size; - total_files += 1; - let mut gap = 0; - - if index > 1 { - let previous_item = &list[index - 1]; - gap = item.position - (previous_item.position + previous_item.size); - } - - total_files_gap += gap; - } - - if let Some(name) = name { - list.retain(|item| item.name.contains(&name)); - }; - - for (index, item) in list.iter().enumerate() { - let mut gap = 0; - - if index > 1 { - let previous_item = &list[index - 1]; - gap = item.position - (previous_item.position + previous_item.size); - } - - let text = format!("Index: {};\nGap: {};\nItem: {:#?};\n", index, gap, item); - stdout.write_line(&text).into_diagnostic()?; - } - - let text = format!( - "Total files: {};\nTotal files gap: {} (bytes);\nTotal files size: {} (bytes);", - total_files, total_files_gap, total_files_size - ); - - stdout.write_line(&text).into_diagnostic()?; - - Ok(()) -} - -fn command_extract(_stdout: console::Term, file: String, out: String, force: bool) -> Result<()> { - let file = std::fs::File::open(file).into_diagnostic()?; - let list = libnres::reader::get_list(&file).into_diagnostic()?; - let bar = indicatif::ProgressBar::new(list.len() as u64); - - bar.set_style(get_bar_style()?); - - for element in list { - bar.set_message(element.get_filename()); - - let path = format!("{}/{}", out, element.get_filename()); - - if !force && is_exist_file(&path) { - let message = format!("File \"{}\" exists. Overwrite it?", path); - - if !dialoguer::Confirm::new() - .with_prompt(message) - .interact() - .into_diagnostic()? - { - continue; - } - } - - let mut output = std::fs::File::create(path).into_diagnostic()?; - let mut buffer = libnres::reader::get_file(&file, &element).into_diagnostic()?; - - output.write_all(&buffer).into_diagnostic()?; - buffer.clear(); - bar.inc(1); - } - - bar.finish(); - - Ok(()) -} - -fn command_ls(stdout: console::Term, file: String) -> Result<()> { - let file = std::fs::File::open(file).into_diagnostic()?; - let list = libnres::reader::get_list(&file).into_diagnostic()?; - - for element in list { - stdout.write_line(&element.name).into_diagnostic()?; - } - - Ok(()) -} - -fn get_bar_style() -> Result { - Ok( - indicatif::ProgressStyle::with_template("[{bar:32}] {pos:>7}/{len:7} {msg}") - .into_diagnostic()? - .progress_chars("=>-"), - ) -} - -fn is_exist_file(path: &String) -> bool { - let metadata = std::path::Path::new(path); - metadata.exists() -} diff --git a/tools/texture-decoder/Cargo.toml b/tools/texture-decoder/Cargo.toml deleted file mode 100644 index 0d11da6..0000000 --- a/tools/texture-decoder/Cargo.toml +++ /dev/null @@ -1,8 +0,0 @@ -[package] -name = "texture-decoder" -version = "0.1.0" -edition = "2021" - -[dependencies] -byteorder = "1.4.3" -image = "0.25.0" diff --git a/tools/texture-decoder/README.md b/tools/texture-decoder/README.md deleted file mode 100644 index 8fca059..0000000 --- a/tools/texture-decoder/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# Декодировщик текстур - -Сборка: - -```bash -cargo build --release -``` - -Запуск: - -```bash -./target/release/texture-decoder ./out/AIM_02.0 ./out/AIM_02.0.png -``` \ No newline at end of file diff --git a/tools/texture-decoder/src/main.rs b/tools/texture-decoder/src/main.rs deleted file mode 100644 index 26c7edd..0000000 --- a/tools/texture-decoder/src/main.rs +++ /dev/null @@ -1,41 +0,0 @@ -use std::io::Read; - -use byteorder::ReadBytesExt; -use image::Rgba; - -fn decode_texture(file_path: &str, output_path: &str) -> Result<(), std::io::Error> { - // Читаем файл - let mut file = std::fs::File::open(file_path)?; - let mut buffer: Vec = Vec::new(); - file.read_to_end(&mut buffer)?; - - // Декодируем метаданные - let mut cursor = std::io::Cursor::new(&buffer[4..]); - let img_width = cursor.read_u32::()?; - let img_height = cursor.read_u32::()?; - - // Пропустить оставшиеся байты метаданных - cursor.set_position(20); - - // Извлекаем данные изображения - let image_data = buffer[cursor.position() as usize..].to_vec(); - let img = - image::ImageBuffer::, _>::from_raw(img_width, img_height, image_data.to_vec()) - .expect("Failed to decode image"); - - // Сохраняем изображение - img.save(output_path).unwrap(); - - Ok(()) -} - -fn main() { - let args: Vec = std::env::args().collect(); - - let input = &args[1]; - let output = &args[2]; - - if let Err(err) = decode_texture(input, output) { - eprintln!("Error: {}", err) - } -} diff --git a/tools/unpacker/Cargo.toml b/tools/unpacker/Cargo.toml deleted file mode 100644 index adb64ec..0000000 --- a/tools/unpacker/Cargo.toml +++ /dev/null @@ -1,9 +0,0 @@ -[package] -name = "unpacker" -version = "0.1.1" -edition = "2021" - -[dependencies] -byteorder = "1.4.3" -serde = { version = "1.0.160", features = ["derive"] } -serde_json = "1.0.96" diff --git a/tools/unpacker/README.md b/tools/unpacker/README.md deleted file mode 100644 index 311e0eb..0000000 --- a/tools/unpacker/README.md +++ /dev/null @@ -1,41 +0,0 @@ -# NRes Game Resource Unpacker - -At the moment, this is a demonstration of the NRes game resource unpacking algorithm in action. -It unpacks 100% of the NRes game resources for the game "Parkan: Iron Strategy". -The unpacked resources can be packed again using the [packer](../packer) utility and replace the original game files. - -__Attention!__ -This is a test version of the utility. -It overwrites existing files without asking. - -## Building - -To build the tools, you need to run the following command in the root directory: - -```bash -cargo build --release -``` - -## Running - -You can run the utility with the following command: - -```bash -./target/release/unpacker /path/to/file.ex /path/to/output -``` - -- `/path/to/file.ex`: This is the file containing the game resources that will be unpacked. -- `/path/to/output`: This is the directory where the unpacked files will be placed. - -## How it Works - -The structure describing the packed game resources is not fully understood yet. -Therefore, the utility saves unpacked files in the format `file_name.file_index` because some files have the same name. - -Additionally, an `index.json` file is created, which is important for re-packing the files. -This file lists all the fields that game resources have in their packed form. -It is essential to preserve the file index for the game to function correctly, as the game engine looks for the necessary files by index. - -Files can be replaced and packed back using the [packer](../packer). -The newly obtained game resource files are correctly processed by the game engine. -For example, sounds and 3D models of warbots' weapons were successfully replaced. \ No newline at end of file diff --git a/tools/unpacker/src/main.rs b/tools/unpacker/src/main.rs deleted file mode 100644 index 36a48c7..0000000 --- a/tools/unpacker/src/main.rs +++ /dev/null @@ -1,124 +0,0 @@ -use std::env; -use std::fs::File; -use std::io::{BufReader, BufWriter, Read, Seek, SeekFrom, Write}; - -use byteorder::{ByteOrder, LittleEndian}; -use serde::{Deserialize, Serialize}; - -#[derive(Serialize, Deserialize, Debug)] -pub struct FileHeader { - pub size: u32, - pub total: u32, - pub type1: u32, - pub type2: u32, -} - -#[derive(Serialize, Deserialize, Debug)] -pub struct ListElement { - pub extension: String, - pub index: u32, - pub name: String, - #[serde(skip_serializing)] - pub position: u32, - #[serde(skip_serializing)] - pub size: u32, - pub unknown0: u32, - pub unknown1: u32, - pub unknown2: u32, -} - -fn main() { - let args: Vec = env::args().collect(); - - let input = &args[1]; - let output = &args[2]; - - unpack(String::from(input), String::from(output)); -} - -fn unpack(input: String, output: String) { - let file = File::open(input).unwrap(); - let metadata = file.metadata().unwrap(); - - let mut reader = BufReader::new(file); - let mut list: Vec = Vec::new(); - - // Считываем заголовок файла - let mut header_buffer = [0u8; 16]; - reader.seek(SeekFrom::Start(0)).unwrap(); - reader.read_exact(&mut header_buffer).unwrap(); - - let file_header = FileHeader { - size: LittleEndian::read_u32(&header_buffer[12..16]), - total: LittleEndian::read_u32(&header_buffer[8..12]), - type1: LittleEndian::read_u32(&header_buffer[0..4]), - type2: LittleEndian::read_u32(&header_buffer[4..8]), - }; - - if file_header.type1 != 1936020046 || file_header.type2 != 256 { - panic!("this isn't NRes file"); - } - - if metadata.len() != file_header.size as u64 { - panic!("incorrect size") - } - - // Считываем список файлов - let list_files_start_position = file_header.size - (file_header.total * 64); - let list_files_size = file_header.total * 64; - - let mut list_buffer = vec![0u8; list_files_size as usize]; - reader - .seek(SeekFrom::Start(list_files_start_position as u64)) - .unwrap(); - reader.read_exact(&mut list_buffer).unwrap(); - - if !list_buffer.len().is_multiple_of(64) { - panic!("invalid files list") - } - - for i in 0..(list_buffer.len() / 64) { - let from = i * 64; - let to = (i * 64) + 64; - let chunk: &[u8] = &list_buffer[from..to]; - - let element_list = ListElement { - extension: String::from_utf8_lossy(&chunk[0..4]) - .trim_matches(char::from(0)) - .to_string(), - index: LittleEndian::read_u32(&chunk[60..64]), - name: String::from_utf8_lossy(&chunk[20..56]) - .trim_matches(char::from(0)) - .to_string(), - position: LittleEndian::read_u32(&chunk[56..60]), - size: LittleEndian::read_u32(&chunk[12..16]), - unknown0: LittleEndian::read_u32(&chunk[4..8]), - unknown1: LittleEndian::read_u32(&chunk[8..12]), - unknown2: LittleEndian::read_u32(&chunk[16..20]), - }; - - list.push(element_list) - } - - // Распаковываем файлы в директорию - for element in &list { - let path = format!("{}/{}.{}", output, element.name, element.index); - let mut file = File::create(path).unwrap(); - - let mut file_buffer = vec![0u8; element.size as usize]; - reader - .seek(SeekFrom::Start(element.position as u64)) - .unwrap(); - reader.read_exact(&mut file_buffer).unwrap(); - - file.write_all(&file_buffer).unwrap(); - file_buffer.clear(); - } - - // Выгрузка списка файлов в JSON - let path = format!("{}/{}", output, "index.json"); - let file = File::create(path).unwrap(); - let mut writer = BufWriter::new(file); - serde_json::to_writer_pretty(&mut writer, &list).unwrap(); - writer.flush().unwrap(); -} -- cgit v1.2.3