ReadStream now doesn't use Raw because &[u8] is more flexible and allow read ESH binaries, + cargo fmt
This commit is contained in:
parent
06ebdc6062
commit
1fdcad3548
10 changed files with 54 additions and 55 deletions
|
|
@ -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]
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
mod attributes;
|
||||
mod decoder;
|
||||
mod entity;
|
||||
mod entitylist;
|
||||
|
|
|
|||
1
src/fot/attributes.rs
Normal file
1
src/fot/attributes.rs
Normal file
|
|
@ -0,0 +1 @@
|
|||
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)?;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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 })
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)?;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue