From a52aed893491a4c898ccb9b1f9e7094df0a2ce13 Mon Sep 17 00:00:00 2001 From: mykola2312 <49044616+mykola2312@users.noreply.github.com> Date: Wed, 30 Aug 2023 20:57:05 +0300 Subject: [PATCH] start implementing SGD --- Cargo.lock | 23 +++++++++++++++++++ Cargo.toml | 1 + src/fot.rs | 1 + src/fot/fstring.rs | 4 ++-- src/fot/sgd.rs | 57 ++++++++++++++++++++++++++++++++++++++++++++++ src/fot/stream.rs | 13 +++++++++-- src/fot/tag.rs | 4 ++-- 7 files changed, 97 insertions(+), 6 deletions(-) create mode 100644 src/fot/sgd.rs diff --git a/Cargo.lock b/Cargo.lock index 5a60f05..d394025 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -44,6 +44,12 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + [[package]] name = "fot-save-edit" version = "0.1.0" @@ -52,10 +58,27 @@ dependencies = [ "byteorder", "deflate", "encoding_rs", + "indexmap", "inflate", "memmem", ] +[[package]] +name = "hashbrown" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" + +[[package]] +name = "indexmap" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d" +dependencies = [ + "equivalent", + "hashbrown", +] + [[package]] name = "inflate" version = "0.4.5" diff --git a/Cargo.toml b/Cargo.toml index e0f19f8..27dfe13 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,5 +10,6 @@ anyhow = "1.0.75" byteorder = "1.4.3" deflate = "1.0.0" encoding_rs = "0.8.33" +indexmap = "2.0.0" inflate = "0.4.5" memmem = "0.1.1" diff --git a/src/fot.rs b/src/fot.rs index 60cdb9a..ad61626 100644 --- a/src/fot.rs +++ b/src/fot.rs @@ -2,6 +2,7 @@ mod decoder; mod fstring; mod raw; pub mod save; +mod sgd; mod stream; mod tag; mod world; diff --git a/src/fot/fstring.rs b/src/fot/fstring.rs index 4549709..7bfb37d 100644 --- a/src/fot/fstring.rs +++ b/src/fot/fstring.rs @@ -7,13 +7,13 @@ use std::io::Cursor; // FString - Fallout -#[derive(Debug, PartialEq)] +#[derive(Debug, Hash, PartialEq, Eq)] pub enum FStringEncoding { ANSI, WCS2, } -#[derive(Debug)] +#[derive(Debug, Hash, PartialEq, Eq)] pub struct FString { pub encoding: FStringEncoding, pub enc_len: usize, diff --git a/src/fot/sgd.rs b/src/fot/sgd.rs new file mode 100644 index 0000000..7f0a2b8 --- /dev/null +++ b/src/fot/sgd.rs @@ -0,0 +1,57 @@ +use super::decoder::Decoder; +use super::fstring::FString; +use super::raw::Raw; +use super::stream::{ReadStream, WriteStream}; +use super::tag::Tag; +use anyhow::Result; +use indexmap::IndexMap; + +pub struct SGD { + tag: Tag, + unk1: Vec, + pub dialogs: IndexMap>, + enc_size: usize, +} + +impl Decoder for SGD { + fn decode(raw: &Raw, offset: usize, size: usize) -> Result { + let mut rd = ReadStream::new(raw, offset); + let tag: Tag = rd.read(0)?; + let unk1 = rd.read_bytes(0x48)?; + let mut dialogs: IndexMap> = IndexMap::new(); + + let n = rd.read_u32()? as usize; + let mut names: Vec = Vec::with_capacity(n); + for _ in 0..n { + names.push(rd.read::(0)?); + } + + let m = rd.read_u32()? as usize; + assert!(m == n, "SGD m != n"); + for _ in 0..m { + let k = rd.read_u32()? as usize; + let mut lines: Vec = Vec::with_capacity(k); + for _ in 0..k { + lines.push(rd.read::(0)?); + } + + dialogs.insert(names.remove(m), lines); + } + + let enc_size = rd.offset() - offset; + Ok(SGD { + tag, + unk1, + dialogs, + enc_size, + }) + } + + fn encode(&self) -> Result { + todo!(); + } + + fn get_enc_size(&self) -> usize { + todo!() + } +} diff --git a/src/fot/stream.rs b/src/fot/stream.rs index 170145b..95cfa8c 100644 --- a/src/fot/stream.rs +++ b/src/fot/stream.rs @@ -1,5 +1,6 @@ use super::decoder::Decoder; use super::raw::Raw; +use anyhow::anyhow; use anyhow::Result; use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; use std::io::Cursor; @@ -10,9 +11,9 @@ pub struct ReadStream<'a> { } impl<'a> ReadStream<'a> { - pub fn new(raw: &Raw, start: usize) -> ReadStream { + pub fn new(raw: &Raw, offset: usize) -> ReadStream { let mut rdr = Cursor::new(&raw.mem[..]); - rdr.set_position(start as u64); + rdr.set_position(offset as u64); ReadStream { raw: raw, rdr: rdr } } @@ -24,6 +25,14 @@ impl<'a> ReadStream<'a> { self.rdr.set_position(self.rdr.position() + size as u64); } + pub fn read_bytes(&mut self, size: usize) -> Result> { + if self.offset() + size > self.raw.mem.len() { + Err(anyhow!("read_bytes size is bigger than buffer")) + } else { + Ok(self.raw.mem[self.offset()..self.offset() + size].to_vec()) + } + } + pub fn read(&mut self, size: usize) -> Result { let val = T::decode(&self.raw, self.offset(), size)?; self.skip(val.get_enc_size()); diff --git a/src/fot/tag.rs b/src/fot/tag.rs index 1e4bd61..b21e66f 100644 --- a/src/fot/tag.rs +++ b/src/fot/tag.rs @@ -1,6 +1,6 @@ -use super::stream::{ReadStream, WriteStream}; use super::decoder::Decoder; use super::raw::Raw; +use super::stream::{ReadStream, WriteStream}; use anyhow::Result; #[derive(Debug)] @@ -20,7 +20,7 @@ impl Decoder for Tag { fn encode(&self) -> Result { let mut wd = WriteStream::new(self.get_enc_size()); wd.write(&self.name)?; - wd.write(&self.version)?; + wd.write(&self.version)?; Ok(wd.into_raw(0, self.get_enc_size())) }