cargo fmt

This commit is contained in:
mykola2312 2023-08-29 23:01:44 +03:00
parent b43efe1abd
commit 584d361095
7 changed files with 142 additions and 92 deletions

View file

@ -1,6 +1,6 @@
use std::str;
use anyhow::Result;
use super::raw::Raw; use super::raw::Raw;
use anyhow::Result;
use std::str;
pub trait Decoder: Sized { pub trait Decoder: Sized {
fn decode(raw: &Raw, offset: usize, size: usize) -> Result<Self>; fn decode(raw: &Raw, offset: usize, size: usize) -> Result<Self>;
@ -13,14 +13,18 @@ impl Decoder for String {
let str = &raw.mem[offset..]; let str = &raw.mem[offset..];
match str.iter().position(|&c| c == 0) { match str.iter().position(|&c| c == 0) {
Some(pos) => Ok(str::from_utf8(&str[..pos])?.to_string()), Some(pos) => Ok(str::from_utf8(&str[..pos])?.to_string()),
None => Ok(str::from_utf8(&raw.mem[offset..offset+size])?.to_string()) None => Ok(str::from_utf8(&raw.mem[offset..offset + size])?.to_string()),
} }
} }
fn encode(&self) -> Result<Raw> { fn encode(&self) -> Result<Raw> {
let mut str = self.as_bytes().to_vec(); let mut str = self.as_bytes().to_vec();
str.push(0); str.push(0);
Ok(Raw { offset: 0, size: str.len(), mem: str}) Ok(Raw {
offset: 0,
size: str.len(),
mem: str,
})
} }
fn get_enc_size(&self) -> usize { fn get_enc_size(&self) -> usize {

View file

@ -1,39 +1,52 @@
use super::decoder::Decoder; use super::decoder::Decoder;
use super::raw::Raw; use super::raw::Raw;
use anyhow::Result; use anyhow::Result;
use std::io::Cursor;
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use encoding_rs::WINDOWS_1251; use encoding_rs::WINDOWS_1251;
use std::io::Cursor;
// FString - Fallout // FString - Fallout
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
pub enum FStringEncoding { pub enum FStringEncoding {
ANSI, ANSI,
WCS2 WCS2,
} }
#[derive(Debug)] #[derive(Debug)]
pub struct FString { pub struct FString {
pub encoding: FStringEncoding, pub encoding: FStringEncoding,
pub enc_len: usize, pub enc_len: usize,
pub str: String pub str: String,
} }
impl Decoder for FString { impl Decoder for FString {
fn decode(raw: &Raw, offset: usize, _: usize) -> Result<Self> { fn decode(raw: &Raw, offset: usize, _: usize) -> Result<Self> {
let mut rdr = Cursor::new(&raw.mem[offset..]); let mut rdr = Cursor::new(&raw.mem[offset..]);
let flen = rdr.read_u32::<LittleEndian>()? as usize; let flen = rdr.read_u32::<LittleEndian>()? as usize;
let len = flen & !(1<<31); let len = flen & !(1 << 31);
let start = offset + 4; let start = offset + 4;
if flen & (1<<31) == 0 { // ANSI if flen & (1 << 31) == 0 {
let (str, _, _) = WINDOWS_1251.decode(&raw.mem[start..start+len]); // ANSI
Ok(FString { encoding: FStringEncoding::ANSI, enc_len: len, str: str.to_string() }) let (str, _, _) = WINDOWS_1251.decode(&raw.mem[start..start + len]);
} else { // WCS2 Ok(FString {
let chars: Vec<u8> = raw.mem[start..start+len*2] encoding: FStringEncoding::ANSI,
.iter().step_by(2).copied().collect(); enc_len: len,
str: str.to_string(),
})
} else {
// WCS2
let chars: Vec<u8> = raw.mem[start..start + len * 2]
.iter()
.step_by(2)
.copied()
.collect();
let (str, _, _) = WINDOWS_1251.decode(&chars); let (str, _, _) = WINDOWS_1251.decode(&chars);
Ok(FString { encoding: FStringEncoding::WCS2, enc_len: len, str: str.to_string() }) Ok(FString {
encoding: FStringEncoding::WCS2,
enc_len: len,
str: str.to_string(),
})
} }
} }
@ -42,22 +55,27 @@ impl Decoder for FString {
let mut wdr = Cursor::new(&mut buf[..]); let mut wdr = Cursor::new(&mut buf[..]);
let (chars, _, _) = WINDOWS_1251.encode(self.str.as_str()); let (chars, _, _) = WINDOWS_1251.encode(self.str.as_str());
if self.encoding == FStringEncoding::ANSI { if self.encoding == FStringEncoding::ANSI {
wdr.write_u32::<LittleEndian>(chars.len() as u32 & !(1<<31))?; wdr.write_u32::<LittleEndian>(chars.len() as u32 & !(1 << 31))?;
buf.extend(chars.iter()); buf.extend(chars.iter());
} else { // WCS2 } else {
wdr.write_u32::<LittleEndian>(chars.len() as u32 | (1<<31))?; // WCS2
wdr.write_u32::<LittleEndian>(chars.len() as u32 | (1 << 31))?;
for &c in chars.iter() { for &c in chars.iter() {
buf.push(c); buf.push(c);
buf.push(0); buf.push(0);
} }
}; };
Ok(Raw { offset: 0, size: buf.len(), mem: buf }) Ok(Raw {
offset: 0,
size: buf.len(),
mem: buf,
})
} }
fn get_enc_size(&self) -> usize { fn get_enc_size(&self) -> usize {
4 + match self.encoding { 4 + match self.encoding {
FStringEncoding::ANSI => self.enc_len, FStringEncoding::ANSI => self.enc_len,
FStringEncoding::WCS2 => self.enc_len * 2 FStringEncoding::WCS2 => self.enc_len * 2,
} }
} }
} }

View file

@ -1,27 +1,31 @@
use std::io::BufWriter; use anyhow::Result;
use std::io::Write; use memmem::{Searcher, TwoWaySearcher};
use std::str;
use std::fs; use std::fs;
use std::fs::OpenOptions; use std::fs::OpenOptions;
use std::io::BufWriter;
use std::io::Write;
use std::path::Path; use std::path::Path;
use memmem::{Searcher, TwoWaySearcher}; use std::str;
use anyhow::Result;
#[derive(Debug)] #[derive(Debug)]
pub struct Raw { pub struct Raw {
pub offset: usize, pub offset: usize,
pub size: usize, pub size: usize,
pub mem: Vec<u8> pub mem: Vec<u8>,
} }
impl Raw { impl Raw {
pub fn join(offset: usize, size: usize, raws: &mut [Raw], ) -> Raw { pub fn join(offset: usize, size: usize, raws: &mut [Raw]) -> Raw {
let mut mem: Vec<u8> = Vec::new(); let mut mem: Vec<u8> = Vec::new();
for raw in raws.iter_mut() { for raw in raws.iter_mut() {
mem.append(&mut raw.mem); mem.append(&mut raw.mem);
} }
Raw { offset: offset, size: size, mem: mem } Raw {
offset: offset,
size: size,
mem: mem,
}
} }
pub fn find_str(&self, str: &str, offset: usize) -> Option<usize> { pub fn find_str(&self, str: &str, offset: usize) -> Option<usize> {
@ -30,10 +34,10 @@ impl Raw {
} }
pub fn find_str_backwards(&self, str: &str) -> Option<usize> { pub fn find_str_backwards(&self, str: &str) -> Option<usize> {
for i in (0..self.mem.len()-str.len()).step_by(1024).rev() { for i in (0..self.mem.len() - str.len()).step_by(1024).rev() {
match self.find_str(str, i) { match self.find_str(str, i) {
Some(offset) => return Some(i+offset), Some(offset) => return Some(i + offset),
None => continue None => continue,
}; };
} }
@ -43,13 +47,21 @@ impl Raw {
pub fn load_file(path: &Path) -> Result<Raw> { pub fn load_file(path: &Path) -> Result<Raw> {
let mem = fs::read(path)?; let mem = fs::read(path)?;
Ok(Self { offset: 0, size: mem.len(), mem }) Ok(Self {
offset: 0,
size: mem.len(),
mem,
})
} }
pub fn assemble_file(&self, path: &Path, blocks: Vec<Raw>) -> Result<()> { pub fn assemble_file(&self, path: &Path, blocks: Vec<Raw>) -> Result<()> {
let mut file = BufWriter::new(OpenOptions::new() let mut file = BufWriter::new(
.create(true).truncate(true).write(true).open(path)?); OpenOptions::new()
.create(true)
.truncate(true)
.write(true)
.open(path)?,
);
let mut sorted = blocks; let mut sorted = blocks;
sorted.sort_by(|a, b| a.offset.cmp(&b.offset)); sorted.sort_by(|a, b| a.offset.cmp(&b.offset));

View file

@ -1,16 +1,16 @@
use std::str; use super::decoder::Decoder;
use std::path::Path; use super::raw::Raw;
use super::world::World;
use anyhow::anyhow; use anyhow::anyhow;
use anyhow::Result; use anyhow::Result;
use byteorder::{ByteOrder, LittleEndian}; use byteorder::{ByteOrder, LittleEndian};
use super::raw::Raw; use std::path::Path;
use super::world::World; use std::str;
use super::decoder::Decoder;
#[derive(Debug)] #[derive(Debug)]
pub struct Save { pub struct Save {
pub raw: Raw, pub raw: Raw,
pub world: World pub world: World,
} }
impl Save { impl Save {
@ -21,21 +21,21 @@ impl Save {
let raw = Raw::load_file(path)?; let raw = Raw::load_file(path)?;
let world_offset = match raw.find_str_backwards(Self::WORLD_TAG) { let world_offset = match raw.find_str_backwards(Self::WORLD_TAG) {
Some(offset) => offset, Some(offset) => offset,
None => return Err(anyhow!("no world found in file")) None => return Err(anyhow!("no world found in file")),
}; };
let mut world_size: usize = 0; let mut world_size: usize = 0;
{ {
let campaign = match raw.find_str(Self::CAMPAIGN_TAG, world_offset) { let campaign = match raw.find_str(Self::CAMPAIGN_TAG, world_offset) {
Some(campaign) => world_offset + campaign, Some(campaign) => world_offset + campaign,
None => return Err(anyhow!("no campaign found after world")) None => return Err(anyhow!("no campaign found after world")),
}; };
for i in (campaign-256..campaign).rev() { for i in (campaign - 256..campaign).rev() {
let fsize = LittleEndian::read_u32(&raw.mem[i..i+4]); let fsize = LittleEndian::read_u32(&raw.mem[i..i + 4]);
if fsize & (1<<31) != 0 { if fsize & (1 << 31) != 0 {
let size = fsize ^ (1<<31); let size = fsize ^ (1 << 31);
if size as usize <= campaign-i { if size as usize <= campaign - i {
world_size = i - world_offset; world_size = i - world_offset;
break; break;
} }
@ -51,9 +51,7 @@ impl Save {
} }
pub fn save(&self, path: &Path) -> Result<()> { pub fn save(&self, path: &Path) -> Result<()> {
self.raw.assemble_file(path, vec![ self.raw.assemble_file(path, vec![self.world.encode()?])?;
self.world.encode()?
])?;
Ok(()) Ok(())
} }

View file

@ -1,25 +1,26 @@
use anyhow::Result;
use super::raw::Raw;
use super::decoder::Decoder; use super::decoder::Decoder;
use super::raw::Raw;
use anyhow::Result;
#[derive(Debug)] #[derive(Debug)]
pub struct Tag { pub struct Tag {
pub name: String, pub name: String,
pub version: String pub version: String,
} }
impl Decoder for Tag { impl Decoder for Tag {
fn decode(raw: &Raw, offset: usize, size: usize) -> Result<Self> { fn decode(raw: &Raw, offset: usize, size: usize) -> Result<Self> {
let name = String::decode(raw, offset, size)?; let name = String::decode(raw, offset, size)?;
let version = String::decode(raw, offset + name.len()+1, 0)?; let version = String::decode(raw, offset + name.len() + 1, 0)?;
Ok(Tag {name, version}) Ok(Tag { name, version })
} }
fn encode(&self) -> Result<Raw> { fn encode(&self) -> Result<Raw> {
Ok(Raw::join(0, self.get_enc_size(), &mut [ Ok(Raw::join(
self.name.encode()?, 0,
self.version.encode()? self.get_enc_size(),
])) &mut [self.name.encode()?, self.version.encode()?],
))
} }
fn get_enc_size(&self) -> usize { fn get_enc_size(&self) -> usize {

View file

@ -1,22 +1,20 @@
use crate::fot::fstring::FStringEncoding;
use super::decoder::Decoder; use super::decoder::Decoder;
use super::fstring::FString;
use super::raw::Raw; use super::raw::Raw;
use super::tag::Tag; use super::tag::Tag;
use super::fstring::FString;
use anyhow::anyhow; use anyhow::anyhow;
use anyhow::Result; use anyhow::Result;
use std::io::Cursor;
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use inflate::inflate_bytes_zlib;
use deflate::deflate_bytes_zlib; use deflate::deflate_bytes_zlib;
use inflate::inflate_bytes_zlib;
use std::io::Cursor;
#[derive(Debug)] #[derive(Debug)]
pub struct World { pub struct World {
pub tag: Tag, pub tag: Tag,
pub uncompressed_size: u32, pub uncompressed_size: u32,
pub data: Raw pub data: Raw,
} }
impl World { impl World {
@ -40,7 +38,7 @@ impl World {
cur += name.get_enc_size(); cur += name.get_enc_size();
names.push(name); names.push(name);
} }
//dbg!(names); dbg!(names);
let unk1 = rdr.read_u32::<LittleEndian>()?; let unk1 = rdr.read_u32::<LittleEndian>()?;
cur += 4; cur += 4;
@ -66,13 +64,21 @@ impl Decoder for World {
fn decode(raw: &Raw, offset: usize, size: usize) -> Result<Self> { fn decode(raw: &Raw, offset: usize, size: usize) -> Result<Self> {
let tag = Tag::decode(raw, offset, Self::WORLD_TAG_LEN)?; let tag = Tag::decode(raw, offset, Self::WORLD_TAG_LEN)?;
let mut rdr = Cursor::new(&raw.mem[offset+Self::WORLD_TAG_LEN..]); let mut rdr = Cursor::new(&raw.mem[offset + Self::WORLD_TAG_LEN..]);
let uncompressed_size = rdr.read_u32::<LittleEndian>()?; let uncompressed_size = rdr.read_u32::<LittleEndian>()?;
let data_start = offset + Self::WORLD_HDR_LEN; let data_start = offset + Self::WORLD_HDR_LEN;
let data = inflate_bytes_zlib(&raw.mem[data_start..data_start+size]) let data =
.map_err(|e| anyhow!(e))?; inflate_bytes_zlib(&raw.mem[data_start..data_start + size]).map_err(|e| anyhow!(e))?;
Ok(World { tag, uncompressed_size, data: Raw { offset, size, mem: data } }) Ok(World {
tag,
uncompressed_size,
data: Raw {
offset,
size,
mem: data,
},
})
} }
fn encode(&self) -> Result<Raw> { fn encode(&self) -> Result<Raw> {
@ -84,11 +90,23 @@ impl Decoder for World {
} }
let data = deflate_bytes_zlib(&self.data.mem); let data = deflate_bytes_zlib(&self.data.mem);
Ok(Raw::join(self.data.offset, self.data.size, &mut [ Ok(Raw::join(
self.tag.encode()?, self.data.offset,
Raw { offset: Self::WORLD_TAG_LEN, size: 8, mem: hdr.to_vec()}, self.data.size,
Raw { offset: Self::WORLD_HDR_LEN, size: data.len(), mem: data} &mut [
])) self.tag.encode()?,
Raw {
offset: Self::WORLD_TAG_LEN,
size: 8,
mem: hdr.to_vec(),
},
Raw {
offset: Self::WORLD_HDR_LEN,
size: data.len(),
mem: data,
},
],
))
} }
fn get_enc_size(&self) -> usize { fn get_enc_size(&self) -> usize {

View file

@ -12,7 +12,6 @@ fn main() {
None => "out.bin" None => "out.bin"
};*/ };*/
let save = Save::load(Path::new(save_path)).expect("load save"); let save = Save::load(Path::new(save_path)).expect("load save");
save.world.test().expect("test"); save.world.test().expect("test");
//save.save(Path::new("out.sav")).expect("failed to save"); //save.save(Path::new("out.sav")).expect("failed to save");