implement full decoding of ESH values

This commit is contained in:
mykola2312 2023-08-31 10:32:24 +03:00
parent 1339b4da9e
commit c69ae933c0
3 changed files with 75 additions and 5 deletions

View file

@ -74,7 +74,7 @@ esh data types
13 - frame, 48 bytes -- multiply all numbers by 4.0. I have strong feeling that it is 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 // a 3x4 translation transform matrix, because one of the dumps showed it was
uint8_t unk1[36] uint8_t unk1[0x24]
float c float c
float b float b
float a float a

View file

@ -49,6 +49,8 @@ pub enum ESHValue {
} }
impl ESHValue { impl ESHValue {
const HDR_SIZE: usize = 8;
const TYPE_BOOL: u32 = 1; const TYPE_BOOL: u32 = 1;
const TYPE_FLOAT: u32 = 2; const TYPE_FLOAT: u32 = 2;
const TYPE_INT: u32 = 3; const TYPE_INT: u32 = 3;
@ -60,6 +62,68 @@ impl ESHValue {
const TYPE_RECT: u32 = 14; const TYPE_RECT: u32 = 14;
} }
impl Decoder for ESHValue {
fn decode(raw: &Raw, offset: usize, _: usize) -> Result<Self> {
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::<FString>(0)?),
Self::TYPE_SPRITE => ESHValue::Sprite(rd.read::<FString>(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<Raw> {
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)] #[derive(Debug)]
pub struct ESH { pub struct ESH {
pub tag: Tag, pub tag: Tag,
@ -76,10 +140,8 @@ impl Decoder for ESH {
let mut props: IndexMap<FString, ESHValue> = IndexMap::with_capacity(n); let mut props: IndexMap<FString, ESHValue> = IndexMap::with_capacity(n);
for _ in 0..n { for _ in 0..n {
let name: FString = rd.read(0)?; let name: FString = rd.read(0)?;
let data_type = rd.read_u32()?; let value: ESHValue = rd.read(0)?;
let data_size = rd.read_u32()? as usize; props.insert(name, value);
let data = rd.read_bytes(data_size)?;
//props.insert(name, ESHValue { data_type, data });
} }
let enc_size = rd.offset() - offset; let enc_size = rd.offset() - offset;

View file

@ -48,6 +48,10 @@ impl<'a> ReadStream<'a> {
Ok(val) Ok(val)
} }
pub fn read_u8(&mut self) -> Result<u8> {
Ok(self.rdr.read_u8()?)
}
pub fn read_u16(&mut self) -> Result<u16> { pub fn read_u16(&mut self) -> Result<u16> {
Ok(self.rdr.read_u16::<LittleEndian>()?) Ok(self.rdr.read_u16::<LittleEndian>()?)
} }
@ -99,6 +103,10 @@ impl WriteStream {
Ok(()) 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<()> { pub fn write_u16(&mut self, val: u16) -> Result<()> {
Ok(self.buf.write_u16::<LittleEndian>(val)?) Ok(self.buf.write_u16::<LittleEndian>(val)?)
} }