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 anyhow::Result;
use std::str;
pub trait Decoder: Sized {
fn decode(raw: &Raw, offset: usize, size: usize) -> Result<Self>;
@ -13,17 +13,21 @@ impl Decoder for String {
let str = &raw.mem[offset..];
match str.iter().position(|&c| c == 0) {
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> {
let mut str = self.as_bytes().to_vec();
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 {
self.len() + 1
}
}
}

View file

@ -1,39 +1,52 @@
use super::decoder::Decoder;
use super::raw::Raw;
use anyhow::Result;
use std::io::Cursor;
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use encoding_rs::WINDOWS_1251;
use std::io::Cursor;
// FString - Fallout
#[derive(Debug, PartialEq)]
pub enum FStringEncoding {
ANSI,
WCS2
WCS2,
}
#[derive(Debug)]
pub struct FString {
pub encoding: FStringEncoding,
pub enc_len: usize,
pub str: String
pub str: String,
}
impl Decoder for FString {
fn decode(raw: &Raw, offset: usize, _: usize) -> Result<Self> {
let mut rdr = Cursor::new(&raw.mem[offset..]);
let flen = rdr.read_u32::<LittleEndian>()? as usize;
let len = flen & !(1<<31);
let len = flen & !(1 << 31);
let start = offset + 4;
if flen & (1<<31) == 0 { // ANSI
let (str, _, _) = WINDOWS_1251.decode(&raw.mem[start..start+len]);
Ok(FString { encoding: FStringEncoding::ANSI, 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();
if flen & (1 << 31) == 0 {
// ANSI
let (str, _, _) = WINDOWS_1251.decode(&raw.mem[start..start + len]);
Ok(FString {
encoding: FStringEncoding::ANSI,
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);
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 (chars, _, _) = WINDOWS_1251.encode(self.str.as_str());
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());
} else { // WCS2
wdr.write_u32::<LittleEndian>(chars.len() as u32 | (1<<31))?;
} else {
// WCS2
wdr.write_u32::<LittleEndian>(chars.len() as u32 | (1 << 31))?;
for &c in chars.iter() {
buf.push(c);
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 {
4 + match self.encoding {
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 std::io::Write;
use std::str;
use anyhow::Result;
use memmem::{Searcher, TwoWaySearcher};
use std::fs;
use std::fs::OpenOptions;
use std::io::BufWriter;
use std::io::Write;
use std::path::Path;
use memmem::{Searcher, TwoWaySearcher};
use anyhow::Result;
use std::str;
#[derive(Debug)]
pub struct Raw {
pub offset: usize,
pub size: usize,
pub mem: Vec<u8>
pub mem: Vec<u8>,
}
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();
for raw in raws.iter_mut() {
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> {
@ -30,10 +34,10 @@ impl Raw {
}
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) {
Some(offset) => return Some(i+offset),
None => continue
Some(offset) => return Some(i + offset),
None => continue,
};
}
@ -42,15 +46,23 @@ impl Raw {
pub fn load_file(path: &Path) -> Result<Raw> {
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<()> {
let mut file = BufWriter::new(OpenOptions::new()
.create(true).truncate(true).write(true).open(path)?);
let mut file = BufWriter::new(
OpenOptions::new()
.create(true)
.truncate(true)
.write(true)
.open(path)?,
);
let mut sorted = blocks;
sorted.sort_by(|a, b| a.offset.cmp(&b.offset));
@ -63,7 +75,7 @@ impl Raw {
file.write(&block.mem)?;
// padding
if block.size > block.mem.len() {
for _ in 0..block.size - block.mem.len() {
for _ in 0..block.size - block.mem.len() {
file.write(&[0])?;
}
}
@ -76,4 +88,4 @@ impl Raw {
file.flush()?;
Ok(())
}
}
}

View file

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

View file

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

View file

@ -1,22 +1,20 @@
use crate::fot::fstring::FStringEncoding;
use super::decoder::Decoder;
use super::fstring::FString;
use super::raw::Raw;
use super::tag::Tag;
use super::fstring::FString;
use anyhow::anyhow;
use anyhow::Result;
use std::io::Cursor;
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use inflate::inflate_bytes_zlib;
use deflate::deflate_bytes_zlib;
use inflate::inflate_bytes_zlib;
use std::io::Cursor;
#[derive(Debug)]
pub struct World {
pub tag: Tag,
pub uncompressed_size: u32,
pub data: Raw
pub data: Raw,
}
impl World {
@ -28,11 +26,11 @@ impl World {
let mut cur = sgd_start;
cur += Tag::decode(&self.data, sgd_start, 0)?.get_enc_size();
cur += 0x48;
let mut rdr = Cursor::new(&self.data.mem[..]);
rdr.set_position(cur as u64);
let N = rdr.read_u32::<LittleEndian>()?;
let mut names: Vec<FString> = Vec::new();
cur += 4;
for _ in 0..N {
@ -40,7 +38,7 @@ impl World {
cur += name.get_enc_size();
names.push(name);
}
//dbg!(names);
dbg!(names);
let unk1 = rdr.read_u32::<LittleEndian>()?;
cur += 4;
@ -65,14 +63,22 @@ impl World {
impl Decoder for World {
fn decode(raw: &Raw, offset: usize, size: usize) -> Result<Self> {
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 data_start = offset + Self::WORLD_HDR_LEN;
let data = 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 } })
let data =
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,
},
})
}
fn encode(&self) -> Result<Raw> {
@ -84,14 +90,26 @@ impl Decoder for World {
}
let data = deflate_bytes_zlib(&self.data.mem);
Ok(Raw::join(self.data.offset, self.data.size, &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}
]))
Ok(Raw::join(
self.data.offset,
self.data.size,
&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 {
Self::WORLD_HDR_LEN + self.data.mem.len()
}
}
}

View file

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