ReadStream now doesn't use Raw because &[u8] is more flexible and allow read ESH binaries, + cargo fmt

This commit is contained in:
mykola2312 2023-09-08 19:52:01 +03:00
parent 06ebdc6062
commit 1fdcad3548
10 changed files with 54 additions and 55 deletions

View file

@ -106,7 +106,6 @@ Attribute - ESH
int derived[26] int derived[26]
int skills[18] int skills[18]
bool skill_tags[18] bool skill_tags[18]
bool opt_traits[27] bool opt_traits[38]
bool type[11]
int perks[111] int perks[111]
int addictions[10] int addictions[10]

View file

@ -1,3 +1,4 @@
mod attributes;
mod decoder; mod decoder;
mod entity; mod entity;
mod entitylist; mod entitylist;

1
src/fot/attributes.rs Normal file
View file

@ -0,0 +1 @@

View file

@ -19,7 +19,7 @@ impl Decoder for String {
let bytes = rd.as_byte_arr(); let bytes = rd.as_byte_arr();
let pos = match bytes.iter().position(|&c| c == 0) { let pos = match bytes.iter().position(|&c| c == 0) {
Some(pos) => pos, Some(pos) => pos,
None => return Err(anyhow!("No zero-terminator found")) None => return Err(anyhow!("No zero-terminator found")),
}; };
let str = str::from_utf8(rd.as_bytes(pos)?)?; let str = str::from_utf8(rd.as_bytes(pos)?)?;
rd.skip(1); rd.skip(1);

View file

@ -1,11 +1,11 @@
use super::decoder::{DecoderCtx, Decoder}; use super::decoder::{Decoder, DecoderCtx};
use super::entity::Entity; use super::entity::Entity;
use super::fstring::{FString, FStringEncoding}; use super::fstring::{FString, FStringEncoding};
use super::stream::{ReadStream, WriteStream}; use super::stream::{ReadStream, WriteStream};
use super::tag::{Tag, CTag}; use super::tag::{CTag, Tag};
use std::path::Path;
use anyhow::Result;
use anyhow::anyhow; use anyhow::anyhow;
use anyhow::Result;
use std::path::Path;
#[derive(Clone, Copy, PartialEq)] #[derive(Clone, Copy, PartialEq)]
pub enum EntityEncoding { pub enum EntityEncoding {
@ -65,7 +65,7 @@ impl EntityList {
pub fn dump_to_entfile(&self, ent: &Entity, path: &Path) -> Result<()> { pub fn dump_to_entfile(&self, ent: &Entity, path: &Path) -> Result<()> {
let esh = match &ent.esh { let esh = match &ent.esh {
Some(esh) => esh, Some(esh) => esh,
None => return Err(anyhow!("entity has no esh")) None => return Err(anyhow!("entity has no esh")),
}; };
let tag = DEFAULT_ENTITY_TAG.to_tag(); let tag = DEFAULT_ENTITY_TAG.to_tag();

View file

@ -93,14 +93,14 @@ impl Decoder for ESHValue {
let entity_id = rd.read_u16()?; let entity_id = rd.read_u16()?;
let flags = rd.read_u16()?; let flags = rd.read_u16()?;
ESHValue::EntityFlags(ESHEntityFlags { entity_id, flags }) ESHValue::EntityFlags(ESHEntityFlags { entity_id, flags })
}, }
Self::TYPE_FRAME => { Self::TYPE_FRAME => {
let unk1 = rd.read_bytes(0x24)?; let unk1 = rd.read_bytes(0x24)?;
let c = rd.read_f32()? * 4.; let c = rd.read_f32()? * 4.;
let b = rd.read_f32()? * 4.; let b = rd.read_f32()? * 4.;
let a = rd.read_f32()? * 4.; let a = rd.read_f32()? * 4.;
ESHValue::Frame(ESHFrame { unk1, a, b, c }) ESHValue::Frame(ESHFrame { unk1, a, b, c })
}, }
Self::TYPE_RECT => { Self::TYPE_RECT => {
let top = rd.read_i32()?; let top = rd.read_i32()?;
let left = rd.read_i32()?; let left = rd.read_i32()?;
@ -112,7 +112,7 @@ impl Decoder for ESHValue {
right, right,
bottom, bottom,
}) })
}, }
_ => { _ => {
let data = rd.read_bytes(data_size as usize)?; let data = rd.read_bytes(data_size as usize)?;
ESHValue::Unknown(ESHUnknown { data_type, data }) ESHValue::Unknown(ESHUnknown { data_type, data })
@ -127,56 +127,56 @@ impl Decoder for ESHValue {
wd.write_u32(unk.data.len() as u32)?; wd.write_u32(unk.data.len() as u32)?;
wd.write_bytes(&unk.data); wd.write_bytes(&unk.data);
}, }
ESHValue::Bool(val) => { ESHValue::Bool(val) => {
wd.write_u32(Self::TYPE_BOOL)?; wd.write_u32(Self::TYPE_BOOL)?;
wd.write_u32(1)?; wd.write_u32(1)?;
wd.write_u8(*val as u8)?; wd.write_u8(*val as u8)?;
}, }
ESHValue::Float(val) => { ESHValue::Float(val) => {
wd.write_u32(Self::TYPE_FLOAT)?; wd.write_u32(Self::TYPE_FLOAT)?;
wd.write_u32(4)?; wd.write_u32(4)?;
wd.write_f32(*val)?; wd.write_f32(*val)?;
}, }
ESHValue::Int(val) => { ESHValue::Int(val) => {
wd.write_u32(Self::TYPE_INT)?; wd.write_u32(Self::TYPE_INT)?;
wd.write_u32(4)?; wd.write_u32(4)?;
wd.write_i32(*val)?; wd.write_i32(*val)?;
}, }
ESHValue::String(str) => { ESHValue::String(str) => {
wd.write_u32(Self::TYPE_STRING)?; wd.write_u32(Self::TYPE_STRING)?;
wd.write_u32(str.get_enc_size() as u32)?; wd.write_u32(str.get_enc_size() as u32)?;
wd.write(str)?; wd.write(str)?;
}, }
ESHValue::Sprite(spr) => { ESHValue::Sprite(spr) => {
wd.write_u32(Self::TYPE_SPRITE)?; wd.write_u32(Self::TYPE_SPRITE)?;
wd.write_u32(spr.get_enc_size() as u32)?; wd.write_u32(spr.get_enc_size() as u32)?;
wd.write(spr)?; wd.write(spr)?;
}, }
ESHValue::Enum(spr) => { ESHValue::Enum(spr) => {
wd.write_u32(Self::TYPE_ENUM)?; wd.write_u32(Self::TYPE_ENUM)?;
wd.write_u32(spr.get_enc_size() as u32)?; wd.write_u32(spr.get_enc_size() as u32)?;
wd.write(spr)?; wd.write(spr)?;
}, }
ESHValue::Binary(bin) => { ESHValue::Binary(bin) => {
wd.write_u32(Self::TYPE_ESBIN)?; wd.write_u32(Self::TYPE_ESBIN)?;
wd.write_u32(bin.len() as u32)?; wd.write_u32(bin.len() as u32)?;
wd.write_bytes(bin); wd.write_bytes(bin);
}, }
ESHValue::EntityFlags(eflags) => { ESHValue::EntityFlags(eflags) => {
wd.write_u32(Self::TYPE_ENTTITYFLAGS)?; wd.write_u32(Self::TYPE_ENTTITYFLAGS)?;
wd.write_u32(ESHEntityFlags::SIZE as u32)?; wd.write_u32(ESHEntityFlags::SIZE as u32)?;
wd.write_u16(eflags.entity_id)?; wd.write_u16(eflags.entity_id)?;
wd.write_u16(eflags.flags)?; wd.write_u16(eflags.flags)?;
}, }
ESHValue::Frame(frame) => { ESHValue::Frame(frame) => {
wd.write_u32(Self::TYPE_FRAME)?; wd.write_u32(Self::TYPE_FRAME)?;
wd.write_u32(ESHFrame::SIZE as u32)?; wd.write_u32(ESHFrame::SIZE as u32)?;
@ -185,7 +185,7 @@ impl Decoder for ESHValue {
wd.write_f32(frame.c / 4.)?; wd.write_f32(frame.c / 4.)?;
wd.write_f32(frame.b / 4.)?; wd.write_f32(frame.b / 4.)?;
wd.write_f32(frame.a / 4.)?; wd.write_f32(frame.a / 4.)?;
}, }
ESHValue::Rect(rect) => { ESHValue::Rect(rect) => {
wd.write_u32(Self::TYPE_RECT)?; wd.write_u32(Self::TYPE_RECT)?;
wd.write_u32(ESHRect::SIZE as u32)?; wd.write_u32(ESHRect::SIZE as u32)?;

View file

@ -38,11 +38,7 @@ impl Decoder for FString {
} else { } else {
// WCS2 // WCS2
let bytes = rd.as_bytes(len * 2)?; let bytes = rd.as_bytes(len * 2)?;
let chars: Vec<u8> = bytes let chars: Vec<u8> = bytes.iter().step_by(2).copied().collect();
.iter()
.step_by(2)
.copied()
.collect();
let (str, _, _) = WINDOWS_1251.decode(&chars); let (str, _, _) = WINDOWS_1251.decode(&chars);
Ok(FString { Ok(FString {
encoding: FStringEncoding::WCS2, encoding: FStringEncoding::WCS2,

View file

@ -46,7 +46,7 @@ impl Save {
return Err(anyhow!("Unable to determine world block size")); return Err(anyhow!("Unable to determine world block size"));
} }
let mut rd = ReadStream::new(&raw, world_offset); let mut rd = ReadStream::new(&raw.mem, world_offset);
let world = World::decode(&mut rd, (world_offset, world_size))?; let world = World::decode(&mut rd, (world_offset, world_size))?;
Ok(Save { raw, world }) Ok(Save { raw, world })
} }

View file

@ -6,15 +6,15 @@ use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use std::io::Cursor; use std::io::Cursor;
pub struct ReadStream<'a> { pub struct ReadStream<'a> {
raw: &'a Raw, mem: &'a [u8],
rdr: Cursor<&'a [u8]>, rdr: Cursor<&'a [u8]>,
} }
impl<'a> ReadStream<'a> { impl<'a> ReadStream<'a> {
pub fn new(raw: &'a Raw, offset: usize) -> ReadStream<'a> { pub fn new(mem: &'a [u8], offset: usize) -> ReadStream<'a> {
let mut rdr = Cursor::new(&raw.mem[..]); let mut rdr = Cursor::new(mem);
rdr.set_position(offset as u64); rdr.set_position(offset as u64);
ReadStream { raw: raw, rdr: rdr } ReadStream { mem, rdr }
} }
pub fn offset(&self) -> usize { pub fn offset(&self) -> usize {
@ -26,7 +26,7 @@ impl<'a> ReadStream<'a> {
} }
pub fn size(&self) -> usize { pub fn size(&self) -> usize {
self.raw.mem.len() self.mem.len()
} }
pub fn is_end(&self) -> bool { pub fn is_end(&self) -> bool {
@ -34,15 +34,15 @@ impl<'a> ReadStream<'a> {
} }
pub fn as_byte_arr(&self) -> &[u8] { pub fn as_byte_arr(&self) -> &[u8] {
&self.raw.mem[self.offset()..] &self.mem[self.offset()..]
} }
pub fn as_bytes(&mut self, size: usize) -> Result<&'a [u8]> { pub fn as_bytes(&mut self, size: usize) -> Result<&'a [u8]> {
if self.offset() + size > self.raw.mem.len() { if self.offset() + size > self.mem.len() {
dbg!(self.offset(), size, self.raw.mem.len()); dbg!(self.offset(), size, self.mem.len());
Err(anyhow!("as_bytes/read_bytes size is bigger than buffer")) Err(anyhow!("as_bytes/read_bytes size is bigger than buffer"))
} else { } else {
let buf = &self.raw.mem[self.offset()..self.offset() + size]; let buf = &self.mem[self.offset()..self.offset() + size];
self.skip(size); self.skip(size);
Ok(buf) Ok(buf)
} }

View file

@ -11,8 +11,8 @@ use anyhow::Result;
use deflate::deflate_bytes_zlib; use deflate::deflate_bytes_zlib;
use inflate::inflate_bytes_zlib; use inflate::inflate_bytes_zlib;
use super::esh::{ESHValue, ESH};
use std::path::Path; use std::path::Path;
use super::esh::{ESH, ESHValue};
pub struct World { pub struct World {
pub offset: usize, pub offset: usize,
@ -21,14 +21,13 @@ pub struct World {
pub tag: Tag, pub tag: Tag,
pub uncompressed_size: u32, pub uncompressed_size: u32,
//pub data: Raw, //pub data: Raw,
pub mission: FString, pub mission: FString,
pub sgd: SGD, pub sgd: SGD,
pub ssg: SSG, pub ssg: SSG,
pub entlist: EntityList, pub entlist: EntityList,
pub unparsed: Vec<u8> pub unparsed: Vec<u8>,
} }
impl World { impl World {
@ -45,8 +44,18 @@ impl World {
println!(""); println!("");
if let ESHValue::Binary(attributes) = &esh.props["Attributes"] { if let ESHValue::Binary(attributes) = &esh.props["Attributes"] {
let raw = Raw { offset: 0, size: attributes.len(), mem: attributes.to_vec() }; let mut rd = ReadStream::new(&attributes, 0);
let mut rd = ReadStream::new(&raw, 0);
let size = rd.read_u32()?;
let attrs_esh: ESH = rd.read()?;
for (name, value) in &attrs_esh.props {
println!("{} {}", name, value);
}
}
println!("");
if let ESHValue::Binary(attributes) = &esh.props["Modifiers"] {
let mut rd = ReadStream::new(&attributes, 0);
let size = rd.read_u32()?; let size = rd.read_u32()?;
let attrs_esh: ESH = rd.read()?; let attrs_esh: ESH = rd.read()?;
@ -69,14 +78,7 @@ impl DecoderCtx<WorldOffsetSize,()> for World {
let uncompressed_size = enc.read_u32()?; let uncompressed_size = enc.read_u32()?;
enc.skip(4); enc.skip(4);
let data = { let data = inflate_bytes_zlib(enc.as_bytes(size)?).map_err(|e| anyhow!(e))?;
let inflated = inflate_bytes_zlib(enc.as_bytes(size)?).map_err(|e| anyhow!(e))?;
Raw {
offset,
size,
mem: inflated,
}
};
let mut rd = ReadStream::new(&data, 0); let mut rd = ReadStream::new(&data, 0);
let mission: FString = rd.read()?; let mission: FString = rd.read()?;
@ -85,7 +87,7 @@ impl DecoderCtx<WorldOffsetSize,()> for World {
let entlist: EntityList = rd.read_ctx(0, EntityEncoding::World)?; let entlist: EntityList = rd.read_ctx(0, EntityEncoding::World)?;
let unparsed = rd.read_bytes(data.mem.len() - rd.offset())?; let unparsed = rd.read_bytes(data.len() - rd.offset())?;
Ok(World { Ok(World {
offset, offset,