diff --git a/format.txt b/format.txt index 29396ea..88b9b1b 100644 --- a/format.txt +++ b/format.txt @@ -74,7 +74,7 @@ esh data types 13 - frame, 48 bytes -- multiply all numbers by 4.0. I have strong feeling that it is // a 3x4 translation transform matrix, because one of the dumps showed it was - uint8_t unk1[36] + uint8_t unk1[0x24] float c float b float a diff --git a/src/fot/esh.rs b/src/fot/esh.rs index 501c5e7..bcda46b 100644 --- a/src/fot/esh.rs +++ b/src/fot/esh.rs @@ -49,6 +49,8 @@ pub enum ESHValue { } impl ESHValue { + const HDR_SIZE: usize = 8; + const TYPE_BOOL: u32 = 1; const TYPE_FLOAT: u32 = 2; const TYPE_INT: u32 = 3; @@ -60,6 +62,68 @@ impl ESHValue { const TYPE_RECT: u32 = 14; } +impl Decoder for ESHValue { + fn decode(raw: &Raw, offset: usize, _: usize) -> Result { + let mut rd = ReadStream::new(raw, offset); + let data_type = rd.read_u32()?; + let data_size = rd.read_u32()?; + + Ok(match data_type { + Self::TYPE_BOOL => ESHValue::Bool(rd.read_u8()? == 1), + Self::TYPE_FLOAT => ESHValue::Float(rd.read_f32()?), + Self::TYPE_INT => ESHValue::Int(rd.read_i32()?), + Self::TYPE_STRING => ESHValue::String(rd.read::(0)?), + Self::TYPE_SPRITE => ESHValue::Sprite(rd.read::(0)?), + Self::TYPE_ESBIN => { + let bin_size = rd.read_u32()?; + ESHValue::Binary(rd.read_bytes(bin_size as usize)?) + }, + Self::TYPE_ENTTITYFLAGS => { + 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()?; + let right = rd.read_i32()?; + let bottom = rd.read_i32()?; + ESHValue::Rect(ESHRect { top, left, right, bottom }) + }, + _ => { + let data = rd.read_bytes(data_size as usize)?; + ESHValue::Unknown(ESHUnknown { data_type, data }) + } + }) + } + + fn encode(&self) -> Result { + todo!(); + } + + fn get_enc_size(&self) -> usize { + Self::HDR_SIZE + match self { + ESHValue::Unknown(unk) => unk.data.len(), + ESHValue::Bool(_) => 1, + ESHValue::Float(_) => 4, + ESHValue::Int(_) => 4, + ESHValue::String(str) => str.get_enc_size(), + ESHValue::Sprite(spr) => spr.get_enc_size(), + ESHValue::Binary(bin) => bin.len(), + ESHValue::EntityFlags(_) => 4, + ESHValue::Frame(_) => 0x30, + ESHValue::Rect(_) => 0x10 + } + } +} + #[derive(Debug)] pub struct ESH { pub tag: Tag, @@ -76,10 +140,8 @@ impl Decoder for ESH { let mut props: IndexMap = IndexMap::with_capacity(n); for _ in 0..n { let name: FString = rd.read(0)?; - let data_type = rd.read_u32()?; - let data_size = rd.read_u32()? as usize; - let data = rd.read_bytes(data_size)?; - //props.insert(name, ESHValue { data_type, data }); + let value: ESHValue = rd.read(0)?; + props.insert(name, value); } let enc_size = rd.offset() - offset; diff --git a/src/fot/stream.rs b/src/fot/stream.rs index 59b205a..2c7d313 100644 --- a/src/fot/stream.rs +++ b/src/fot/stream.rs @@ -48,6 +48,10 @@ impl<'a> ReadStream<'a> { Ok(val) } + pub fn read_u8(&mut self) -> Result { + Ok(self.rdr.read_u8()?) + } + pub fn read_u16(&mut self) -> Result { Ok(self.rdr.read_u16::()?) } @@ -99,6 +103,10 @@ impl WriteStream { Ok(()) } + pub fn write_u8(&mut self, val: u8) -> Result<()> { + Ok(self.buf.write_u8(val)?) + } + pub fn write_u16(&mut self, val: u16) -> Result<()> { Ok(self.buf.write_u16::(val)?) }