start implementing SGD

This commit is contained in:
mykola2312 2023-08-30 20:57:05 +03:00
parent 236bf7fdca
commit a52aed8934
7 changed files with 97 additions and 6 deletions

23
Cargo.lock generated
View file

@ -44,6 +44,12 @@ dependencies = [
"cfg-if", "cfg-if",
] ]
[[package]]
name = "equivalent"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
[[package]] [[package]]
name = "fot-save-edit" name = "fot-save-edit"
version = "0.1.0" version = "0.1.0"
@ -52,10 +58,27 @@ dependencies = [
"byteorder", "byteorder",
"deflate", "deflate",
"encoding_rs", "encoding_rs",
"indexmap",
"inflate", "inflate",
"memmem", "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]] [[package]]
name = "inflate" name = "inflate"
version = "0.4.5" version = "0.4.5"

View file

@ -10,5 +10,6 @@ anyhow = "1.0.75"
byteorder = "1.4.3" byteorder = "1.4.3"
deflate = "1.0.0" deflate = "1.0.0"
encoding_rs = "0.8.33" encoding_rs = "0.8.33"
indexmap = "2.0.0"
inflate = "0.4.5" inflate = "0.4.5"
memmem = "0.1.1" memmem = "0.1.1"

View file

@ -2,6 +2,7 @@ mod decoder;
mod fstring; mod fstring;
mod raw; mod raw;
pub mod save; pub mod save;
mod sgd;
mod stream; mod stream;
mod tag; mod tag;
mod world; mod world;

View file

@ -7,13 +7,13 @@ use std::io::Cursor;
// FString - Fallout // FString - Fallout
#[derive(Debug, PartialEq)] #[derive(Debug, Hash, PartialEq, Eq)]
pub enum FStringEncoding { pub enum FStringEncoding {
ANSI, ANSI,
WCS2, WCS2,
} }
#[derive(Debug)] #[derive(Debug, Hash, PartialEq, Eq)]
pub struct FString { pub struct FString {
pub encoding: FStringEncoding, pub encoding: FStringEncoding,
pub enc_len: usize, pub enc_len: usize,

57
src/fot/sgd.rs Normal file
View file

@ -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<u8>,
pub dialogs: IndexMap<FString, Vec<FString>>,
enc_size: usize,
}
impl Decoder for SGD {
fn decode(raw: &Raw, offset: usize, size: usize) -> Result<Self> {
let mut rd = ReadStream::new(raw, offset);
let tag: Tag = rd.read(0)?;
let unk1 = rd.read_bytes(0x48)?;
let mut dialogs: IndexMap<FString, Vec<FString>> = IndexMap::new();
let n = rd.read_u32()? as usize;
let mut names: Vec<FString> = Vec::with_capacity(n);
for _ in 0..n {
names.push(rd.read::<FString>(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<FString> = Vec::with_capacity(k);
for _ in 0..k {
lines.push(rd.read::<FString>(0)?);
}
dialogs.insert(names.remove(m), lines);
}
let enc_size = rd.offset() - offset;
Ok(SGD {
tag,
unk1,
dialogs,
enc_size,
})
}
fn encode(&self) -> Result<Raw> {
todo!();
}
fn get_enc_size(&self) -> usize {
todo!()
}
}

View file

@ -1,5 +1,6 @@
use super::decoder::Decoder; use super::decoder::Decoder;
use super::raw::Raw; use super::raw::Raw;
use anyhow::anyhow;
use anyhow::Result; use anyhow::Result;
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use std::io::Cursor; use std::io::Cursor;
@ -10,9 +11,9 @@ pub struct ReadStream<'a> {
} }
impl<'a> 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[..]); let mut rdr = Cursor::new(&raw.mem[..]);
rdr.set_position(start as u64); rdr.set_position(offset as u64);
ReadStream { raw: raw, rdr: rdr } ReadStream { raw: raw, rdr: rdr }
} }
@ -24,6 +25,14 @@ impl<'a> ReadStream<'a> {
self.rdr.set_position(self.rdr.position() + size as u64); self.rdr.set_position(self.rdr.position() + size as u64);
} }
pub fn read_bytes(&mut self, size: usize) -> Result<Vec<u8>> {
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<T: Decoder>(&mut self, size: usize) -> Result<T> { pub fn read<T: Decoder>(&mut self, size: usize) -> Result<T> {
let val = T::decode(&self.raw, self.offset(), size)?; let val = T::decode(&self.raw, self.offset(), size)?;
self.skip(val.get_enc_size()); self.skip(val.get_enc_size());

View file

@ -1,6 +1,6 @@
use super::stream::{ReadStream, WriteStream};
use super::decoder::Decoder; use super::decoder::Decoder;
use super::raw::Raw; use super::raw::Raw;
use super::stream::{ReadStream, WriteStream};
use anyhow::Result; use anyhow::Result;
#[derive(Debug)] #[derive(Debug)]
@ -20,7 +20,7 @@ impl Decoder for Tag {
fn encode(&self) -> Result<Raw> { fn encode(&self) -> Result<Raw> {
let mut wd = WriteStream::new(self.get_enc_size()); let mut wd = WriteStream::new(self.get_enc_size());
wd.write(&self.name)?; wd.write(&self.name)?;
wd.write(&self.version)?; wd.write(&self.version)?;
Ok(wd.into_raw(0, self.get_enc_size())) Ok(wd.into_raw(0, self.get_enc_size()))
} }