implemented EntityList decoding and encoding. But decoding has some bugs that needs to be fixed
This commit is contained in:
parent
4e8cc4a5e8
commit
5ea616cd44
6 changed files with 52 additions and 49 deletions
|
|
@ -8,9 +8,9 @@ pub trait Decoder: Sized {
|
||||||
fn get_enc_size(&self) -> usize;
|
fn get_enc_size(&self) -> usize;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait DecoderCtx<Ctx>: Sized {
|
pub trait DecoderCtx<DCtx, ECtx>: Sized {
|
||||||
fn decode(raw: &Raw, offset: usize, size: usize, ctx: Ctx) -> Result<Self>;
|
fn decode(raw: &Raw, offset: usize, size: usize, ctx: DCtx) -> Result<Self>;
|
||||||
fn encode(&self, ctx: Ctx) -> Result<Raw>;
|
fn encode(&self, ctx: ECtx) -> Result<Raw>;
|
||||||
fn get_enc_size(&self) -> usize;
|
fn get_enc_size(&self) -> usize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ pub struct Entity {
|
||||||
enc_size: usize,
|
enc_size: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DecoderCtx<&mut EntityList> for Entity {
|
impl DecoderCtx<&mut EntityList, &EntityList> for Entity {
|
||||||
fn decode(raw: &Raw, offset: usize, _: usize, ctx: &mut EntityList) -> Result<Self> {
|
fn decode(raw: &Raw, offset: usize, _: usize, ctx: &mut EntityList) -> Result<Self> {
|
||||||
let mut rd = ReadStream::new(raw, offset);
|
let mut rd = ReadStream::new(raw, offset);
|
||||||
Ok(match ctx.get_entity_encoding() {
|
Ok(match ctx.get_entity_encoding() {
|
||||||
|
|
@ -45,11 +45,10 @@ impl DecoderCtx<&mut EntityList> for Entity {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encode(&self, ctx: &mut EntityList) -> Result<Raw> {
|
fn encode(&self, ctx: &EntityList) -> Result<Raw> {
|
||||||
let mut wd = WriteStream::new(self.get_enc_size());
|
let mut wd = WriteStream::new(self.get_enc_size());
|
||||||
match ctx.get_entity_encoding() {
|
match ctx.get_entity_encoding() {
|
||||||
EntityEncoding::File => {
|
EntityEncoding::File => {
|
||||||
wd.write(ctx.get_entity_tag())?;
|
|
||||||
wd.write(ctx.get_type_name(self.type_idx))?;
|
wd.write(ctx.get_type_name(self.type_idx))?;
|
||||||
wd.write(&self.esh)?;
|
wd.write(&self.esh)?;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,8 +21,8 @@ pub struct EntityList {
|
||||||
unk1: u32,
|
unk1: u32,
|
||||||
enc_size: usize,
|
enc_size: usize,
|
||||||
|
|
||||||
types: Vec<FString>,
|
pub types: Vec<FString>,
|
||||||
entities: Vec<Entity>
|
pub entities: Vec<Entity>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EntityList {
|
impl EntityList {
|
||||||
|
|
@ -51,7 +51,7 @@ impl EntityList {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DecoderCtx<EntityEncoding> for EntityList {
|
impl DecoderCtx<EntityEncoding,EntityEncoding> for EntityList {
|
||||||
fn decode(raw: &Raw, offset: usize, size: usize, ctx: EntityEncoding) -> Result<Self> {
|
fn decode(raw: &Raw, offset: usize, size: usize, ctx: EntityEncoding) -> Result<Self> {
|
||||||
let mut rd = ReadStream::new(raw, offset);
|
let mut rd = ReadStream::new(raw, offset);
|
||||||
let mut ent_list = EntityList {
|
let mut ent_list = EntityList {
|
||||||
|
|
@ -84,15 +84,16 @@ impl DecoderCtx<EntityEncoding> for EntityList {
|
||||||
|
|
||||||
EntityEncoding::World => {
|
EntityEncoding::World => {
|
||||||
ent_list.entity_file_tag = Some(rd.read(0)?);
|
ent_list.entity_file_tag = Some(rd.read(0)?);
|
||||||
let n = rd.read_u32()?;
|
let type_count = rd.read_u32()?;
|
||||||
for _ in 0..n {
|
for _ in 0..type_count {
|
||||||
ent_list.types.push(rd.read(0)?);
|
ent_list.types.push(rd.read(0)?);
|
||||||
}
|
}
|
||||||
|
|
||||||
let m = rd.read_u16()?;
|
let ent_count = rd.read_u16()?;
|
||||||
ent_list.unk1 = rd.read_u32()?;
|
ent_list.unk1 = rd.read_u32()?;
|
||||||
for _ in 0..m {
|
for i in 1..ent_count {
|
||||||
let ent: Entity = rd.read_opt(0, &mut ent_list)?;
|
let ent: Entity = rd.read_opt(0, &mut ent_list)?;
|
||||||
|
println!("ok read {}", i);
|
||||||
ent_list.entities.push(ent);
|
ent_list.entities.push(ent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -103,7 +104,30 @@ impl DecoderCtx<EntityEncoding> for EntityList {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encode(&self, ctx: EntityEncoding) -> Result<Raw> {
|
fn encode(&self, ctx: EntityEncoding) -> Result<Raw> {
|
||||||
todo!();
|
let mut wd = WriteStream::new(self.get_enc_size());
|
||||||
|
match ctx {
|
||||||
|
EntityEncoding::File => {
|
||||||
|
for ent in self.entities.iter() {
|
||||||
|
wd.write(self.get_entity_tag())?;
|
||||||
|
wd.write_opt(ent, &self)?;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
EntityEncoding::World => {
|
||||||
|
wd.write(self.entity_file_tag.as_ref().unwrap())?;
|
||||||
|
wd.write_u32(self.types.len() as u32)?;
|
||||||
|
for type_name in self.types.iter() {
|
||||||
|
wd.write(type_name)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
wd.write_u16(self.entities.len() as u16)?;
|
||||||
|
wd.write_u32(self.unk1)?;
|
||||||
|
for ent in self.entities.iter() {
|
||||||
|
wd.write_opt(ent, &self)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(wd.into_raw(0, 0))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_enc_size(&self) -> usize {
|
fn get_enc_size(&self) -> usize {
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,6 @@ use byteorder::{ByteOrder, LittleEndian};
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::str;
|
use std::str;
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct Save {
|
pub struct Save {
|
||||||
pub raw: Raw,
|
pub raw: Raw,
|
||||||
pub world: World,
|
pub world: World,
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,7 @@ impl<'a> ReadStream<'a> {
|
||||||
|
|
||||||
// read_opt - decode with optional paramters. required for complex structure
|
// read_opt - decode with optional paramters. required for complex structure
|
||||||
// with different origins (save / entfile) like entities
|
// with different origins (save / entfile) like entities
|
||||||
pub fn read_opt<T: DecoderCtx<Ctx>, Ctx>(&mut self, size: usize, ctx: Ctx) -> Result<T> {
|
pub fn read_opt<T: DecoderCtx<DCtx, ECtx>, DCtx, ECtx>(&mut self, size: usize, ctx: DCtx) -> Result<T> {
|
||||||
let val = T::decode(&self.raw, self.offset(), size, ctx)?;
|
let val = T::decode(&self.raw, self.offset(), size, ctx)?;
|
||||||
self.skip(val.get_enc_size());
|
self.skip(val.get_enc_size());
|
||||||
Ok(val)
|
Ok(val)
|
||||||
|
|
@ -112,6 +112,13 @@ impl WriteStream {
|
||||||
self.buf.get_mut().extend(bytes.iter());
|
self.buf.get_mut().extend(bytes.iter());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn write_opt<T: DecoderCtx<DCtx, ECtx>, DCtx, ECtx>(&mut self, val: &T, ctx: ECtx) -> Result<()> {
|
||||||
|
let mut raw = val.encode(ctx)?;
|
||||||
|
self.skip(raw.mem.len());
|
||||||
|
self.buf.get_mut().append(&mut raw.mem);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn write<T: Decoder>(&mut self, val: &T) -> Result<()> {
|
pub fn write<T: Decoder>(&mut self, val: &T) -> Result<()> {
|
||||||
let mut raw = val.encode()?;
|
let mut raw = val.encode()?;
|
||||||
self.skip(raw.mem.len());
|
self.skip(raw.mem.len());
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use super::decoder::Decoder;
|
use super::decoder::Decoder;
|
||||||
use super::esh::ESH;
|
|
||||||
use super::fstring::FString;
|
use super::fstring::FString;
|
||||||
|
use super::entitylist::{EntityList, EntityEncoding};
|
||||||
use super::raw::Raw;
|
use super::raw::Raw;
|
||||||
use super::sgd::SGD;
|
use super::sgd::SGD;
|
||||||
use super::ssg::SSG;
|
use super::ssg::SSG;
|
||||||
|
|
@ -13,7 +13,6 @@ use deflate::deflate_bytes_zlib;
|
||||||
use inflate::inflate_bytes_zlib;
|
use inflate::inflate_bytes_zlib;
|
||||||
use std::io::Cursor;
|
use std::io::Cursor;
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct World {
|
pub struct World {
|
||||||
pub tag: Tag,
|
pub tag: Tag,
|
||||||
pub uncompressed_size: u32,
|
pub uncompressed_size: u32,
|
||||||
|
|
@ -23,6 +22,8 @@ pub struct World {
|
||||||
pub mission: FString,
|
pub mission: FString,
|
||||||
pub sgd: SGD,
|
pub sgd: SGD,
|
||||||
pub ssg: SSG,
|
pub ssg: SSG,
|
||||||
|
|
||||||
|
pub ents: EntityList
|
||||||
}
|
}
|
||||||
|
|
||||||
impl World {
|
impl World {
|
||||||
|
|
@ -30,37 +31,7 @@ impl World {
|
||||||
const WORLD_HDR_LEN: usize = 0x13;
|
const WORLD_HDR_LEN: usize = 0x13;
|
||||||
|
|
||||||
pub fn test(&self) -> Result<()> {
|
pub fn test(&self) -> Result<()> {
|
||||||
let mut rd = ReadStream::new(&self.data, 0x1038);
|
println!("read {} ents", self.ents.entities.len());
|
||||||
let _: Tag = rd.read(0)?;
|
|
||||||
|
|
||||||
let n = rd.read_u32()? as usize;
|
|
||||||
let mut types: Vec<FString> = Vec::with_capacity(n);
|
|
||||||
for i in 0..n {
|
|
||||||
let ent_type: FString = rd.read(0)?;
|
|
||||||
println!("{}\t{}", i, &ent_type);
|
|
||||||
types.push(ent_type);
|
|
||||||
}
|
|
||||||
|
|
||||||
let esh_count = rd.read_u16()?;
|
|
||||||
let unk1 = rd.read_u32()?;
|
|
||||||
dbg!(esh_count);
|
|
||||||
for i in 1..esh_count {
|
|
||||||
let unk2 = rd.read_u32()?;
|
|
||||||
let type_idx = rd.read_u16()?;
|
|
||||||
if type_idx == 0xFFFF {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
let name = &types[type_idx as usize];
|
|
||||||
println!(
|
|
||||||
"offset {:x} idx {} unk1 {} name {}",
|
|
||||||
rd.offset(),
|
|
||||||
i,
|
|
||||||
unk2,
|
|
||||||
name
|
|
||||||
);
|
|
||||||
let _: ESH = rd.read(0)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
@ -88,6 +59,8 @@ impl Decoder for World {
|
||||||
let sgd: SGD = rd.read(0)?;
|
let sgd: SGD = rd.read(0)?;
|
||||||
let ssg: SSG = rd.read(0)?;
|
let ssg: SSG = rd.read(0)?;
|
||||||
|
|
||||||
|
let ents: EntityList = rd.read_opt(0, EntityEncoding::World)?;
|
||||||
|
|
||||||
Ok(World {
|
Ok(World {
|
||||||
tag,
|
tag,
|
||||||
uncompressed_size,
|
uncompressed_size,
|
||||||
|
|
@ -95,6 +68,7 @@ impl Decoder for World {
|
||||||
mission,
|
mission,
|
||||||
sgd,
|
sgd,
|
||||||
ssg,
|
ssg,
|
||||||
|
ents
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue