diff options
Diffstat (limited to 'libnres')
-rw-r--r-- | libnres/Cargo.toml | 16 | ||||
-rw-r--r-- | libnres/README.md | 25 | ||||
-rw-r--r-- | libnres/src/converter.rs | 33 | ||||
-rw-r--r-- | libnres/src/error.rs | 45 | ||||
-rw-r--r-- | libnres/src/lib.rs | 24 | ||||
-rw-r--r-- | libnres/src/reader.rs | 227 |
6 files changed, 0 insertions, 370 deletions
diff --git a/libnres/Cargo.toml b/libnres/Cargo.toml deleted file mode 100644 index 99539e7..0000000 --- a/libnres/Cargo.toml +++ /dev/null @@ -1,16 +0,0 @@ -[package] -name = "libnres" -version = "0.1.4" -description = "Library for NRes files" -authors = ["Valentin Popov <valentin@popov.link>"] -homepage = "https://git.popov.link/valentineus/fparkan" -repository = "https://git.popov.link/valentineus/fparkan.git" -license = "GPL-2.0" -edition = "2021" -keywords = ["gamedev", "library", "nres"] - -[dependencies] -byteorder = "1.4" -log = "0.4" -miette = "7.0" -thiserror = "2.0" diff --git a/libnres/README.md b/libnres/README.md deleted file mode 100644 index 065bd40..0000000 --- a/libnres/README.md +++ /dev/null @@ -1,25 +0,0 @@ -# Library for NRes files (Deprecated) - -Library for viewing and retrieving game resources of the game **"Parkan: Iron Strategy"**. -All versions of the game are supported: Demo, IS, IS: Part 1, IS: Part 2. -Supports files with `lib`, `trf`, `rlb` extensions. - -The files `gamefont.rlb` and `sprites.lib` are not supported. -This files have an unknown signature. - -## Example - -Example of extracting game resources: - -```rust -fn main() { - let file = std::fs::File::open("./voices.lib").unwrap(); - // Extracting the list of files - let list = libnres::reader::get_list(&file).unwrap(); - - for element in list { - // Extracting the contents of the file - let data = libnres::reader::get_file(&file, &element).unwrap(); - } -} -``` diff --git a/libnres/src/converter.rs b/libnres/src/converter.rs deleted file mode 100644 index bbf0535..0000000 --- a/libnres/src/converter.rs +++ /dev/null @@ -1,33 +0,0 @@ -use crate::error::ConverterError; - -/// Method for converting u32 to u64. -pub fn u32_to_u64(value: u32) -> Result<u64, ConverterError> { - match u64::try_from(value) { - Err(error) => Err(ConverterError::Infallible(error)), - Ok(result) => Ok(result), - } -} - -/// Method for converting u32 to usize. -pub fn u32_to_usize(value: u32) -> Result<usize, ConverterError> { - match usize::try_from(value) { - Err(error) => Err(ConverterError::TryFromIntError(error)), - Ok(result) => Ok(result), - } -} - -/// Method for converting u64 to u32. -pub fn u64_to_u32(value: u64) -> Result<u32, ConverterError> { - match u32::try_from(value) { - Err(error) => Err(ConverterError::TryFromIntError(error)), - Ok(result) => Ok(result), - } -} - -/// Method for converting usize to u32. -pub fn usize_to_u32(value: usize) -> Result<u32, ConverterError> { - match u32::try_from(value) { - Err(error) => Err(ConverterError::TryFromIntError(error)), - Ok(result) => Ok(result), - } -} diff --git a/libnres/src/error.rs b/libnres/src/error.rs deleted file mode 100644 index 440ab06..0000000 --- a/libnres/src/error.rs +++ /dev/null @@ -1,45 +0,0 @@ -extern crate miette; -extern crate thiserror; - -use miette::Diagnostic; -use thiserror::Error; - -#[derive(Error, Diagnostic, Debug)] -pub enum ConverterError { - #[error("error converting an value")] - #[diagnostic(code(libnres::infallible))] - Infallible(#[from] std::convert::Infallible), - - #[error("error converting an value")] - #[diagnostic(code(libnres::try_from_int_error))] - TryFromIntError(#[from] std::num::TryFromIntError), -} - -#[derive(Error, Diagnostic, Debug)] -pub enum ReaderError { - #[error(transparent)] - #[diagnostic(code(libnres::convert_error))] - ConvertValue(#[from] ConverterError), - - #[error("incorrect header format")] - #[diagnostic(code(libnres::list_type_error))] - IncorrectHeader, - - #[error("incorrect file size (expected {expected:?} bytes, received {received:?} bytes)")] - #[diagnostic(code(libnres::file_size_error))] - IncorrectSizeFile { expected: u32, received: u32 }, - - #[error( - "incorrect size of the file list (not a multiple of {expected:?}, received {received:?})" - )] - #[diagnostic(code(libnres::list_size_error))] - IncorrectSizeList { expected: u32, received: u32 }, - - #[error("resource file reading error")] - #[diagnostic(code(libnres::io_error))] - ReadFile(#[from] std::io::Error), - - #[error("file is too small (must be at least {expected:?} bytes, received {received:?} byte)")] - #[diagnostic(code(libnres::file_size_error))] - SmallFile { expected: u32, received: u32 }, -} diff --git a/libnres/src/lib.rs b/libnres/src/lib.rs deleted file mode 100644 index 40c0b32..0000000 --- a/libnres/src/lib.rs +++ /dev/null @@ -1,24 +0,0 @@ -/// First constant value of the NRes file ("NRes" characters in numeric) -pub const FILE_TYPE_1: u32 = 1936020046; -/// Second constant value of the NRes file -pub const FILE_TYPE_2: u32 = 256; -/// Size of the element item (in bytes) -pub const LIST_ELEMENT_SIZE: u32 = 64; -/// Minimum allowed file size (in bytes) -pub const MINIMUM_FILE_SIZE: u32 = 16; - -static DEBUG: std::sync::atomic::AtomicBool = std::sync::atomic::AtomicBool::new(false); - -mod converter; -mod error; -pub mod reader; - -/// Get debug status value -pub fn get_debug() -> bool { - DEBUG.load(std::sync::atomic::Ordering::Relaxed) -} - -/// Change debug status value -pub fn set_debug(value: bool) { - DEBUG.store(value, std::sync::atomic::Ordering::Relaxed) -} diff --git a/libnres/src/reader.rs b/libnres/src/reader.rs deleted file mode 100644 index 2a450ee..0000000 --- a/libnres/src/reader.rs +++ /dev/null @@ -1,227 +0,0 @@ -use std::io::{Read, Seek}; - -use byteorder::ByteOrder; - -use crate::error::ReaderError; -use crate::{converter, FILE_TYPE_1, FILE_TYPE_2, LIST_ELEMENT_SIZE, MINIMUM_FILE_SIZE}; - -#[derive(Debug)] -pub struct ListElement { - /// Unknown parameter - _unknown0: i32, - /// Unknown parameter - _unknown1: i32, - /// Unknown parameter - _unknown2: i32, - /// File extension - pub extension: String, - /// Identifier or sequence number - pub index: u32, - /// File name - pub name: String, - /// Position in the file - pub position: u32, - /// File size (in bytes) - pub size: u32, -} - -impl ListElement { - /// Get full name of the file - pub fn get_filename(&self) -> String { - format!("{}.{}", self.name, self.extension) - } -} - -#[derive(Debug)] -pub struct FileHeader { - /// File size - size: u32, - /// Number of files - total: u32, - /// First constant value - type1: u32, - /// Second constant value - type2: u32, -} - -/// Get a packed file data -pub fn get_file(file: &std::fs::File, element: &ListElement) -> Result<Vec<u8>, ReaderError> { - let size = get_file_size(file)?; - check_file_size(size)?; - - let header = get_file_header(file)?; - check_file_header(&header, size)?; - - let data = get_element_data(file, element)?; - Ok(data) -} - -/// Get a list of packed files -pub fn get_list(file: &std::fs::File) -> Result<Vec<ListElement>, ReaderError> { - let mut list: Vec<ListElement> = Vec::new(); - - let size = get_file_size(file)?; - check_file_size(size)?; - - let header = get_file_header(file)?; - check_file_header(&header, size)?; - - get_file_list(file, &header, &mut list)?; - - Ok(list) -} - -fn check_file_header(header: &FileHeader, size: u32) -> Result<(), ReaderError> { - if header.type1 != FILE_TYPE_1 || header.type2 != FILE_TYPE_2 { - return Err(ReaderError::IncorrectHeader); - } - - if header.size != size { - return Err(ReaderError::IncorrectSizeFile { - expected: size, - received: header.size, - }); - } - - Ok(()) -} - -fn check_file_size(size: u32) -> Result<(), ReaderError> { - if size < MINIMUM_FILE_SIZE { - return Err(ReaderError::SmallFile { - expected: MINIMUM_FILE_SIZE, - received: size, - }); - } - - Ok(()) -} - -fn get_element_data(file: &std::fs::File, element: &ListElement) -> Result<Vec<u8>, ReaderError> { - let position = converter::u32_to_u64(element.position)?; - let size = converter::u32_to_usize(element.size)?; - - let mut reader = std::io::BufReader::new(file); - let mut buffer = vec![0u8; size]; - - if let Err(error) = reader.seek(std::io::SeekFrom::Start(position)) { - return Err(ReaderError::ReadFile(error)); - }; - - if let Err(error) = reader.read_exact(&mut buffer) { - return Err(ReaderError::ReadFile(error)); - }; - - Ok(buffer) -} - -fn get_element_position(index: u32) -> Result<(usize, usize), ReaderError> { - let from = converter::u32_to_usize(index * LIST_ELEMENT_SIZE)?; - let to = converter::u32_to_usize((index * LIST_ELEMENT_SIZE) + LIST_ELEMENT_SIZE)?; - Ok((from, to)) -} - -fn get_file_header(file: &std::fs::File) -> Result<FileHeader, ReaderError> { - let mut reader = std::io::BufReader::new(file); - let mut buffer = vec![0u8; MINIMUM_FILE_SIZE as usize]; - - if let Err(error) = reader.seek(std::io::SeekFrom::Start(0)) { - return Err(ReaderError::ReadFile(error)); - }; - - if let Err(error) = reader.read_exact(&mut buffer) { - return Err(ReaderError::ReadFile(error)); - }; - - let header = FileHeader { - size: byteorder::LittleEndian::read_u32(&buffer[12..16]), - total: byteorder::LittleEndian::read_u32(&buffer[8..12]), - type1: byteorder::LittleEndian::read_u32(&buffer[0..4]), - type2: byteorder::LittleEndian::read_u32(&buffer[4..8]), - }; - - buffer.clear(); - Ok(header) -} - -fn get_file_list( - file: &std::fs::File, - header: &FileHeader, - list: &mut Vec<ListElement>, -) -> Result<(), ReaderError> { - let (start_position, list_size) = get_list_position(header)?; - let mut reader = std::io::BufReader::new(file); - let mut buffer = vec![0u8; list_size]; - - if let Err(error) = reader.seek(std::io::SeekFrom::Start(start_position)) { - return Err(ReaderError::ReadFile(error)); - }; - - if let Err(error) = reader.read_exact(&mut buffer) { - return Err(ReaderError::ReadFile(error)); - } - - let buffer_size = converter::usize_to_u32(buffer.len())?; - - if buffer_size % LIST_ELEMENT_SIZE != 0 { - return Err(ReaderError::IncorrectSizeList { - expected: LIST_ELEMENT_SIZE, - received: buffer_size, - }); - } - - for i in 0..(buffer_size / LIST_ELEMENT_SIZE) { - let (from, to) = get_element_position(i)?; - let chunk: &[u8] = &buffer[from..to]; - - let element = get_list_element(chunk)?; - list.push(element); - } - - buffer.clear(); - Ok(()) -} - -fn get_file_size(file: &std::fs::File) -> Result<u32, ReaderError> { - let metadata = match file.metadata() { - Err(error) => return Err(ReaderError::ReadFile(error)), - Ok(value) => value, - }; - - let result = converter::u64_to_u32(metadata.len())?; - Ok(result) -} - -fn get_list_element(buffer: &[u8]) -> Result<ListElement, ReaderError> { - let index = byteorder::LittleEndian::read_u32(&buffer[60..64]); - let position = byteorder::LittleEndian::read_u32(&buffer[56..60]); - let size = byteorder::LittleEndian::read_u32(&buffer[12..16]); - let unknown0 = byteorder::LittleEndian::read_i32(&buffer[4..8]); - let unknown1 = byteorder::LittleEndian::read_i32(&buffer[8..12]); - let unknown2 = byteorder::LittleEndian::read_i32(&buffer[16..20]); - - let extension = String::from_utf8_lossy(&buffer[0..4]) - .trim_matches(char::from(0)) - .to_string(); - - let name = String::from_utf8_lossy(&buffer[20..56]) - .trim_matches(char::from(0)) - .to_string(); - - Ok(ListElement { - _unknown0: unknown0, - _unknown1: unknown1, - _unknown2: unknown2, - extension, - index, - name, - position, - size, - }) -} - -fn get_list_position(header: &FileHeader) -> Result<(u64, usize), ReaderError> { - let position = converter::u32_to_u64(header.size - (header.total * LIST_ELEMENT_SIZE))?; - let size = converter::u32_to_usize(header.total * LIST_ELEMENT_SIZE)?; - Ok((position, size)) -} |