mirror of
https://github.com/xzeldon/rdr2_screenshot_converter.git
synced 2025-07-15 15:14:39 +03:00
refactor: refactoring code, separate crates
preparing to create a GUI
This commit is contained in:
11
core/Cargo.toml
Normal file
11
core/Cargo.toml
Normal file
@ -0,0 +1,11 @@
|
||||
[package]
|
||||
edition = "2021"
|
||||
name = "core"
|
||||
version = "0.1.0"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
ctrlc = "3.2.1"
|
||||
serde = {version = "1.0.135", features = ["derive"]}
|
||||
winapi = {version = "0.3.9", features = ["consoleapi", "errhandlingapi", "fileapi", "handleapi", "processenv"]}
|
3
core/README.md
Normal file
3
core/README.md
Normal file
@ -0,0 +1,3 @@
|
||||
# Core
|
||||
|
||||
A library that provides functionality such as working with buffers, files, and so on.
|
46
core/src/buffer.rs
Normal file
46
core/src/buffer.rs
Normal file
@ -0,0 +1,46 @@
|
||||
use std::fs::File;
|
||||
use std::io;
|
||||
use std::io::Read;
|
||||
use std::path::PathBuf;
|
||||
|
||||
pub fn is_not_empty(e: &u8) -> bool {
|
||||
*e != 0x00
|
||||
}
|
||||
|
||||
pub fn trim(buffer: &Vec<u8>) -> Vec<u8> {
|
||||
let begin = buffer.iter().position(is_not_empty);
|
||||
let end = buffer
|
||||
.iter()
|
||||
.rev()
|
||||
.position(is_not_empty)
|
||||
.map(|j| buffer.len() - j);
|
||||
let vec = begin
|
||||
.and_then(|i| end.map(|j| buffer[i..j].iter().cloned().collect()))
|
||||
.unwrap_or(Vec::new());
|
||||
vec
|
||||
}
|
||||
|
||||
pub fn read_file(path: &PathBuf) -> Result<Vec<u8>, io::Error> {
|
||||
let mut data = Vec::new();
|
||||
File::open(path)?.read_to_end(&mut data)?;
|
||||
return Ok(data);
|
||||
}
|
||||
|
||||
pub fn find_index(buffer: &Vec<u8>, index: &[u8]) -> usize {
|
||||
let index = buffer
|
||||
.windows(index.len())
|
||||
.position(|window| window == index)
|
||||
.unwrap();
|
||||
index
|
||||
}
|
||||
|
||||
pub fn parse_buf(
|
||||
buffer: &Vec<u8>,
|
||||
first_index: &[u8],
|
||||
last_index: &[u8],
|
||||
offset: usize,
|
||||
) -> Vec<u8> {
|
||||
let first = find_index(&buffer, first_index);
|
||||
let last = find_index(&buffer, last_index);
|
||||
return trim(&buffer[first + offset..last].to_vec());
|
||||
}
|
71
core/src/console.rs
Normal file
71
core/src/console.rs
Normal file
@ -0,0 +1,71 @@
|
||||
#[cfg(windows)]
|
||||
pub fn enable_ansi_support() -> Result<(), u32> {
|
||||
// ref: https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences#EXAMPLE_OF_ENABLING_VIRTUAL_TERMINAL_PROCESSING @@ https://archive.is/L7wRJ#76%
|
||||
|
||||
use std::ffi::OsStr;
|
||||
use std::iter::once;
|
||||
use std::os::windows::ffi::OsStrExt;
|
||||
use std::ptr::null_mut;
|
||||
use winapi::um::consoleapi::{GetConsoleMode, SetConsoleMode};
|
||||
use winapi::um::errhandlingapi::GetLastError;
|
||||
use winapi::um::fileapi::{CreateFileW, OPEN_EXISTING};
|
||||
use winapi::um::handleapi::INVALID_HANDLE_VALUE;
|
||||
use winapi::um::winnt::{FILE_SHARE_WRITE, GENERIC_READ, GENERIC_WRITE};
|
||||
|
||||
const ENABLE_VIRTUAL_TERMINAL_PROCESSING: u32 = 0x0004;
|
||||
|
||||
unsafe {
|
||||
// ref: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilew
|
||||
// Using `CreateFileW("CONOUT$", ...)` to retrieve the console handle works correctly even if STDOUT and/or STDERR are redirected
|
||||
let console_out_name: Vec<u16> =
|
||||
OsStr::new("CONOUT$").encode_wide().chain(once(0)).collect();
|
||||
let console_handle = CreateFileW(
|
||||
console_out_name.as_ptr(),
|
||||
GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_WRITE,
|
||||
null_mut(),
|
||||
OPEN_EXISTING,
|
||||
0,
|
||||
null_mut(),
|
||||
);
|
||||
if console_handle == INVALID_HANDLE_VALUE {
|
||||
return Err(GetLastError());
|
||||
}
|
||||
|
||||
// ref: https://docs.microsoft.com/en-us/windows/console/getconsolemode
|
||||
let mut console_mode: u32 = 0;
|
||||
if 0 == GetConsoleMode(console_handle, &mut console_mode) {
|
||||
return Err(GetLastError());
|
||||
}
|
||||
|
||||
// VT processing not already enabled?
|
||||
if console_mode & ENABLE_VIRTUAL_TERMINAL_PROCESSING == 0 {
|
||||
// https://docs.microsoft.com/en-us/windows/console/setconsolemode
|
||||
if 0 == SetConsoleMode(
|
||||
console_handle,
|
||||
console_mode | ENABLE_VIRTUAL_TERMINAL_PROCESSING,
|
||||
) {
|
||||
return Err(GetLastError());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
pub fn set_ctrl_c_handler() {
|
||||
use std::process;
|
||||
use std::sync;
|
||||
|
||||
let running = sync::Arc::new(sync::atomic::AtomicBool::new(true));
|
||||
let r = running.clone();
|
||||
|
||||
ctrlc::set_handler(move || {
|
||||
r.store(false, sync::atomic::Ordering::SeqCst);
|
||||
})
|
||||
.expect("Error setting Ctrl-C handler");
|
||||
println!("Press Ctrl + C for exit");
|
||||
while running.load(sync::atomic::Ordering::SeqCst) {}
|
||||
println!("Exiting...");
|
||||
process::exit(0);
|
||||
}
|
26
core/src/files.rs
Normal file
26
core/src/files.rs
Normal file
@ -0,0 +1,26 @@
|
||||
use std::path::PathBuf;
|
||||
use std::{fs, io};
|
||||
|
||||
pub fn collect(profile_paths: &Vec<PathBuf>) -> Result<Vec<PathBuf>, io::Error> {
|
||||
let mut prdr3s = Vec::new();
|
||||
|
||||
for path in profile_paths {
|
||||
let entries = fs::read_dir(path)?
|
||||
.map(|res| res.map(|e| e.path()))
|
||||
.collect::<Result<Vec<_>, io::Error>>()?;
|
||||
|
||||
for file in entries {
|
||||
let stem = file.file_stem().unwrap().to_str().unwrap();
|
||||
|
||||
if stem.chars().count() >= 5 {
|
||||
let substr = &stem[0..5];
|
||||
|
||||
if substr == "PRDR3" {
|
||||
prdr3s.push(file)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(prdr3s)
|
||||
}
|
4
core/src/lib.rs
Normal file
4
core/src/lib.rs
Normal file
@ -0,0 +1,4 @@
|
||||
pub mod buffer;
|
||||
pub mod console;
|
||||
pub mod files;
|
||||
pub mod meta;
|
57
core/src/meta.rs
Normal file
57
core/src/meta.rs
Normal file
@ -0,0 +1,57 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct Loc {
|
||||
x: f64,
|
||||
y: f64,
|
||||
z: f64,
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct Time {
|
||||
hour: i32,
|
||||
minute: i32,
|
||||
second: i32,
|
||||
day: i32,
|
||||
month: i32,
|
||||
year: i32,
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(Serialize, Deserialize)]
|
||||
|
||||
pub struct Meta {
|
||||
horse: Option<Vec<i32>>,
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(Serialize, Deserialize)]
|
||||
|
||||
pub struct ImageMetadata {
|
||||
pub loc: Loc,
|
||||
pub regionname: usize,
|
||||
pub districtname: usize,
|
||||
pub statename: usize,
|
||||
pub nm: String,
|
||||
pub sid: String,
|
||||
pub crewid: usize,
|
||||
pub mid: String,
|
||||
pub mode: String,
|
||||
pub meme: bool,
|
||||
pub mug: bool,
|
||||
pub uid: usize,
|
||||
pub time: Time,
|
||||
pub creat: usize,
|
||||
pub slf: bool,
|
||||
pub drctr: bool,
|
||||
pub rsedtr: bool,
|
||||
pub inphotomode: bool,
|
||||
pub advanced: bool,
|
||||
pub width: usize,
|
||||
pub height: usize,
|
||||
pub size: usize,
|
||||
pub sign: usize,
|
||||
pub meta: Meta,
|
||||
}
|
Reference in New Issue
Block a user