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 skills[18]
bool skill_tags[18]
bool opt_traits[27]
bool type[11]
bool opt_traits[38]
int perks[111]
int addictions[10]

View file

@ -1,3 +1,4 @@
mod attributes;
mod decoder;
mod entity;
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 pos = match bytes.iter().position(|&c| c == 0) {
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)?)?;
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::fstring::{FString, FStringEncoding};
use super::stream::{ReadStream, WriteStream};
use super::tag::{Tag, CTag};
use std::path::Path;
use anyhow::Result;
use super::tag::{CTag, Tag};
use anyhow::anyhow;
use anyhow::Result;
use std::path::Path;
#[derive(Clone, Copy, PartialEq)]
pub enum EntityEncoding {
@ -59,13 +59,13 @@ impl EntityList {
}
pub fn get_entity(&self, id: usize) -> &Entity {
&self.ents[id-1]
&self.ents[id - 1]
}
pub fn dump_to_entfile(&self, ent: &Entity, path: &Path) -> Result<()> {
let esh = match &ent.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();
@ -174,4 +174,4 @@ impl<'a> IntoIterator for &'a EntityList {
fn into_iter(self) -> Self::IntoIter {
(1..).zip(&self.ents)
}
}
}

View file

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

View file

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

View file

@ -46,7 +46,7 @@ impl Save {
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))?;
Ok(Save { raw, world })
}

View file

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

View file

@ -11,8 +11,8 @@ use anyhow::Result;
use deflate::deflate_bytes_zlib;
use inflate::inflate_bytes_zlib;
use super::esh::{ESHValue, ESH};
use std::path::Path;
use super::esh::{ESH, ESHValue};
pub struct World {
pub offset: usize,
@ -21,14 +21,13 @@ pub struct World {
pub tag: Tag,
pub uncompressed_size: u32,
//pub data: Raw,
pub mission: FString,
pub sgd: SGD,
pub ssg: SSG,
pub entlist: EntityList,
pub unparsed: Vec<u8>
pub unparsed: Vec<u8>,
}
impl World {
@ -45,8 +44,18 @@ impl World {
println!("");
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(&raw, 0);
let mut rd = ReadStream::new(&attributes, 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 attrs_esh: ESH = rd.read()?;
@ -59,8 +68,8 @@ impl World {
}
}
pub type WorldOffsetSize = (usize,usize);
impl DecoderCtx<WorldOffsetSize,()> for World {
pub type WorldOffsetSize = (usize, usize);
impl DecoderCtx<WorldOffsetSize, ()> for World {
fn decode<'a>(enc: &mut ReadStream<'a>, ctx: WorldOffsetSize) -> Result<Self> {
let offset = ctx.0;
let size = ctx.1;
@ -69,14 +78,7 @@ impl DecoderCtx<WorldOffsetSize,()> for World {
let uncompressed_size = enc.read_u32()?;
enc.skip(4);
let data = {
let inflated = inflate_bytes_zlib(enc.as_bytes(size)?).map_err(|e| anyhow!(e))?;
Raw {
offset,
size,
mem: inflated,
}
};
let data = inflate_bytes_zlib(enc.as_bytes(size)?).map_err(|e| anyhow!(e))?;
let mut rd = ReadStream::new(&data, 0);
let mission: FString = rd.read()?;
@ -85,7 +87,7 @@ impl DecoderCtx<WorldOffsetSize,()> for 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 {
offset,
@ -104,7 +106,7 @@ impl DecoderCtx<WorldOffsetSize,()> for World {
fn encode(&self, wd: &mut WriteStream, _: ()) -> Result<()> {
let data = {
let mut wd = WriteStream::new(self.uncompressed_size as usize);
wd.write(&self.mission)?;
wd.write(&self.sgd)?;
wd.write(&self.ssg)?;