rpfm_lib/files/esf/
mod.rs

1//---------------------------------------------------------------------------//
2// Copyright (c) 2017-2024 Ismael Gutiérrez González. All rights reserved.
3//
4// This file is part of the Rusted PackFile Manager (RPFM) project,
5// which can be found here: https://github.com/Frodo45127/rpfm.
6//
7// This file is licensed under the MIT license, which can be found here:
8// https://github.com/Frodo45127/rpfm/blob/master/LICENSE.
9//---------------------------------------------------------------------------//
10
11//! This is a module to read/write ESF (Empire Safe File) files.
12//!
13//! ESF files are special files used to hold a variety of data, ranging from trade routes info
14//! to entire campaign savestates.
15//!
16//! Due to the huge complexity of these files, the spec is defined in the submodules containing
17//! the logic for each variation of this file.
18
19use bitflags::bitflags;
20use getset::*;
21use serde_derive::{Serialize, Deserialize};
22
23use std::{fmt, fmt::Display};
24
25use crate::binary::{ReadBytes, WriteBytes};
26use crate::error::{Result, RLibError};
27use crate::files::{DecodeableExtraData, Decodeable, EncodeableExtraData, Encodeable};
28
29/// Extensions used by ESF files.
30pub const EXTENSIONS: [&str; 6] = [
31    ".csc",                 // CSC files.
32    ".ccd",                 // CEO files.
33    ".esf",                 // ESF files.
34    ".save",                // Game save files.
35    ".save_multiplayer",    // Game save files, multiplayer.
36    ".twc",                 // Character save files.
37];
38
39/// Signatured/Magic Numbers/Whatever of a ESF file.
40pub const SIGNATURE_CAAB: &[u8; 4] = &[0xCA, 0xAB, 0x00, 0x00];
41pub const SIGNATURE_CBAB: &[u8; 4] = &[0xCB, 0xAB, 0x00, 0x00];
42pub const SIGNATURE_CEAB: &[u8; 4] = &[0xCE, 0xAB, 0x00, 0x00];
43pub const SIGNATURE_CFAB: &[u8; 4] = &[0xCF, 0xAB, 0x00, 0x00];
44
45mod caab;
46mod cbab;
47mod utils;
48
49#[cfg(test)] mod esf_test;
50
51//---------------------------------------------------------------------------//
52//                              Markers, from ESFEdit
53//---------------------------------------------------------------------------//
54
55// Invalid marker.
56pub const INVALID: u8 = 0x00;
57
58// Primitives
59const BOOL: u8 = 0x01;
60const I8: u8 = 0x02;
61const I16: u8 = 0x03;
62const I32: u8 = 0x04;
63const I64: u8 = 0x05;
64const U8: u8 = 0x06;
65const U16: u8 = 0x07;
66const U32: u8 = 0x08;
67const U64: u8 = 0x09;
68const F32: u8 = 0x0a;
69const F64: u8 = 0x0b;
70const COORD_2D: u8 = 0x0c;
71const COORD_3D: u8 = 0x0d;
72const UTF16: u8 = 0x0e;
73const ASCII: u8 = 0x0f;
74const ANGLE: u8 = 0x10;
75
76// Optimized Primitives
77const BOOL_TRUE: u8 = 0x12;
78const BOOL_FALSE: u8 = 0x13;
79const U32_ZERO: u8 = 0x14;
80const U32_ONE: u8 = 0x15;
81const U32_BYTE: u8 = 0x16;
82const U32_16BIT: u8 = 0x17;
83const U32_24BIT: u8 = 0x18;
84const I32_ZERO: u8 = 0x19;
85const I32_BYTE: u8 = 0x1a;
86const I32_16BIT: u8 = 0x1b;
87const I32_24BIT: u8 = 0x1c;
88const F32_ZERO: u8 = 0x1d;
89
90// Unknown Types
91const UNKNOWN_21: u8 = 0x21;
92const UNKNOWN_23: u8 = 0x23;
93const UNKNOWN_24: u8 = 0x24;
94const UNKNOWN_25: u8 = 0x25;
95
96// Three Kingdoms DLC Eight Princes types
97const UNKNOWN_26: u8 = 0x26;
98
99// Primitive Arrays
100const BOOL_ARRAY: u8 = 0x41;
101const I8_ARRAY: u8 = 0x42;
102const I16_ARRAY: u8 = 0x43;
103const I32_ARRAY: u8 = 0x44;
104const I64_ARRAY: u8 = 0x45;
105const U8_ARRAY: u8 = 0x46;
106const U16_ARRAY: u8 = 0x47;
107const U32_ARRAY: u8 = 0x48;
108const U64_ARRAY: u8 = 0x49;
109const F32_ARRAY: u8 = 0x4a;
110const F64_ARRAY: u8 = 0x4b;
111const COORD_2D_ARRAY: u8 = 0x4c;
112const COORD_3D_ARRAY: u8 = 0x4d;
113const UTF16_ARRAY: u8 = 0x4e;
114const ASCII_ARRAY: u8 = 0x4f;
115const ANGLE_ARRAY: u8 = 0x50;
116
117// Optimized Arrays
118const BOOL_TRUE_ARRAY: u8 = 0x52; // makes no sense
119const BOOL_FALSE_ARRAY: u8 = 0x53; // makes no sense
120const U32_ZERO_ARRAY: u8 = 0x54; // makes no sense
121const U32_ONE_ARRAY: u8 = 0x55; // makes no sense
122const U32_BYTE_ARRAY: u8 = 0x56;
123const U32_16BIT_ARRAY: u8 = 0x57;
124const U32_24BIT_ARRAY: u8 = 0x58;
125const I32_ZERO_ARRAY: u8 = 0x59; // makes no sense
126const I32_BYTE_ARRAY: u8 = 0x5a;
127const I32_16BIT_ARRAY: u8 = 0x5b;
128const I32_24BIT_ARRAY: u8 = 0x5c;
129const F32_ZERO_ARRAY: u8 = 0x5d;  // makes no sense
130
131const COMPRESSED_TAGS: [&str; 1] = ["CAMPAIGN_ENV"];
132const COMPRESSED_DATA_TAG: &str = "COMPRESSED_DATA";
133const COMPRESSED_DATA_INFO_TAG: &str = "COMPRESSED_DATA_INFO";
134
135// Blocks have quite a few bits that can be toggle to change their behavior.
136bitflags! {
137
138    /// This represents the bitmasks a Record Block can have applied to its type byte.
139    #[derive(PartialEq, Clone, Copy, Default, Debug, Serialize, Deserialize)]
140    pub struct RecordNodeFlags: u8 {
141
142        /// Used to specify that the type is indeed a record block.
143        const IS_RECORD_NODE            = 0b1000_0000;
144
145        /// Used to specify that this block contains nested groups of nodes.
146        const HAS_NESTED_BLOCKS         = 0b0100_0000;
147
148        /// Used to specify that this block doesn't use optimized integers for version and name index.
149        const HAS_NON_OPTIMIZED_INFO    = 0b0010_0000;
150    }
151}
152
153//---------------------------------------------------------------------------//
154//                              Enum & Structs
155//---------------------------------------------------------------------------//
156
157/// This holds an entire ESF decoded in memory.
158#[derive(Getters, Setters, PartialEq, Clone, Debug, Default, Serialize, Deserialize)]
159#[getset(get = "pub", set = "pub")]
160pub struct ESF {
161
162    /// Signature of the ESF.
163    signature: ESFSignature,
164
165    /// Unknown value.
166    unknown_1: u32,
167
168    /// Creation date of the ESF.
169    creation_date: u32,
170
171    /// Root node of the node tree, containing the entire ESF data on it.
172    root_node: NodeType,
173}
174
175/// This enum represents the different signatures of ESF files.
176#[derive(Eq, PartialEq, Clone, Copy, Debug, Default, Serialize, Deserialize)]
177pub enum ESFSignature {
178    #[default]CAAB,
179    CBAB,
180    CEAB,
181    CFAB
182}
183
184/// This enum represents all known node types present on ESF files.
185///
186/// NOTE: These are partially extracted from EditSF.
187#[derive(PartialEq, Clone, Debug, Default, Serialize, Deserialize)]
188pub enum NodeType {
189
190    // Invalid type.
191    #[default]
192    Invalid,
193
194    // Primitive nodes.
195    Bool(BoolNode),
196    I8(i8),
197    I16(i16),
198    I32(I32Node),
199    I64(i64),
200    U8(u8),
201    U16(u16),
202    U32(U32Node),
203    U64(u64),
204    F32(F32Node),
205    F64(f64),
206    Coord2d(Coordinates2DNode),
207    Coord3d(Coordinates3DNode),
208    Utf16(String),
209    Ascii(String),
210    Angle(i16),
211
212    // Unknown Types
213    Unknown21(u32),
214    Unknown23(u8),
215    Unknown24(u16),
216    Unknown25(u32),
217    Unknown26(Vec<u8>),
218
219    // Primitive Arrays
220    BoolArray(Vec<bool>),
221    I8Array(Vec<u8>),
222    I16Array(Vec<i16>),
223    I32Array(VecI32Node),
224    I64Array(Vec<i64>),
225    U8Array(Vec<u8>),
226    U16Array(Vec<u16>),
227    U32Array(VecU32Node),
228    U64Array(Vec<u64>),
229    F32Array(Vec<f32>),
230    F64Array(Vec<f64>),
231    Coord2dArray(Vec<Coordinates2DNode>),
232    Coord3dArray(Vec<Coordinates3DNode>),
233    Utf16Array(Vec<String>),
234    AsciiArray(Vec<String>),
235    AngleArray(Vec<i16>),
236
237    // Record nodes
238    Record(Box<RecordNode>),
239}
240
241/// Node containing a bool value, and if the node should be optimized or not.
242#[derive(Getters, MutGetters, Setters, Eq, PartialEq, Clone, Debug, Serialize, Deserialize)]
243#[getset(get = "pub", get_mut = "pub", set = "pub")]
244pub struct BoolNode {
245    value: bool,
246    optimized: bool,
247}
248
249/// Node containing an i32 value, and if the node should be optimized or not.
250#[derive(Getters, MutGetters, Setters, Eq, PartialEq, Clone, Debug, Serialize, Deserialize)]
251#[getset(get = "pub", get_mut = "pub", set = "pub")]
252pub struct I32Node {
253    value: i32,
254    optimized: bool,
255}
256
257/// Node containing an u32 value, and if the node should be optimized or not.
258#[derive(Getters, MutGetters, Setters, Eq, PartialEq, Clone, Debug, Serialize, Deserialize)]
259#[getset(get = "pub", get_mut = "pub", set = "pub")]
260pub struct U32Node {
261    value: u32,
262    optimized: bool,
263}
264
265/// Node containing an f32 value, and if the node should be optimized or not.
266#[derive(Getters, MutGetters, Setters, PartialEq, Clone, Debug, Serialize, Deserialize)]
267#[getset(get = "pub", get_mut = "pub", set = "pub")]
268pub struct F32Node {
269    value: f32,
270    optimized: bool,
271}
272
273/// Node containing a `Vec<i32>`, and if the node should be optimized or not.
274#[derive(Getters, MutGetters, Setters, Eq, PartialEq, Clone, Debug, Serialize, Deserialize)]
275#[getset(get = "pub", get_mut = "pub", set = "pub")]
276pub struct VecI32Node {
277    value: Vec<i32>,
278    optimized: bool,
279}
280
281/// Node containing a `Vec<u32>`, and if the node should be optimized or not.
282#[derive(Getters, MutGetters, Setters, Eq, PartialEq, Clone, Debug, Serialize, Deserialize)]
283#[getset(get = "pub", get_mut = "pub", set = "pub")]
284pub struct VecU32Node {
285    value: Vec<u32>,
286    optimized: bool,
287}
288
289/// Node containing a pair of X/Y coordinates.
290#[derive(Getters, MutGetters, Setters, PartialEq, Clone, Default, Debug, Serialize, Deserialize)]
291#[getset(get = "pub", get_mut = "pub", set = "pub")]
292pub struct Coordinates2DNode {
293    x: f32,
294    y: f32,
295}
296
297/// Node containing a group of X/Y/Z coordinates.
298#[derive(Getters, MutGetters, Setters, PartialEq, Clone, Default, Debug, Serialize, Deserialize)]
299#[getset(get = "pub", get_mut = "pub", set = "pub")]
300pub struct Coordinates3DNode {
301    x: f32,
302    y: f32,
303    z: f32,
304}
305
306/// Node containing a record of data. Basically, a node with other nodes attached to it.
307#[derive(Getters, MutGetters, Setters, PartialEq, Clone, Default, Debug, Serialize, Deserialize)]
308#[getset(get = "pub", get_mut = "pub", set = "pub")]
309pub struct RecordNode {
310
311    /// Flags applied to this record node.
312    record_flags: RecordNodeFlags,
313
314    /// Version of this record node.
315    version: u8,
316
317    /// Name of the record node.
318    name: String,
319
320    /// Children nodes of this record node.
321    children: Vec<Vec<NodeType>>
322}
323
324//---------------------------------------------------------------------------//
325//                           Implementation of ESF
326//---------------------------------------------------------------------------//
327
328/// Implementation of `ESF`.
329impl ESF {
330
331    /// This function creates a copy of an ESF without the root node.
332    pub fn clone_without_root_node(&self) -> Self {
333        Self {
334            signature: self.signature,
335            unknown_1: self.unknown_1,
336            creation_date: self.creation_date,
337            root_node: NodeType::Invalid,
338        }
339    }
340}
341
342/// Implementation of `NodeType`.
343impl NodeType {
344
345    /// This function creates a copy of a node without its children.
346    pub fn clone_without_children(&self) -> Self {
347        match self {
348            Self::Record(node) => {
349                let mut new_node = RecordNode::default();
350                new_node.set_name(node.name().to_owned());
351                new_node.set_record_flags(*node.record_flags());
352                new_node.set_version(*node.version());
353
354                Self::Record(Box::new(new_node))
355            }
356
357            _ => self.clone()
358        }
359    }
360}
361
362/// Display implementation for `ESFSignature`.
363impl Display for ESFSignature {
364    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
365        Display::fmt(match self {
366            Self::CAAB => "CAAB",
367            Self::CBAB => "CBAB",
368            Self::CEAB => "CEAB",
369            Self::CFAB => "CFAB",
370        }, f)
371    }
372}
373
374impl TryFrom<&str> for ESFSignature {
375    type Error = RLibError;
376
377    fn try_from(value: &str) -> Result<Self, Self::Error> {
378        match value {
379            "CAAB" => Ok(Self::CAAB),
380            "CBAB" => Ok(Self::CBAB),
381            "CEAB" => Ok(Self::CEAB),
382            "CFAB" => Ok(Self::CFAB),
383            _ => Err(RLibError::UnknownESFSignature(value.to_string())),
384        }
385    }
386}
387
388impl TryFrom<Vec<u8>> for ESFSignature {
389    type Error = RLibError;
390
391    fn try_from(value: Vec<u8>) -> Result<Self, Self::Error> {
392        match value.as_slice().try_into()? {
393            SIGNATURE_CAAB => Ok(Self::CAAB),
394            SIGNATURE_CBAB => Ok(Self::CBAB),
395            SIGNATURE_CEAB => Ok(Self::CEAB),
396            SIGNATURE_CFAB => Ok(Self::CFAB),
397            _ => Err(RLibError::UnknownESFSignatureBytes(value[0], value[1])),
398        }
399    }
400}
401
402impl From<ESFSignature> for Vec<u8> {
403    fn from(value: ESFSignature) -> Self {
404        match value {
405            ESFSignature::CAAB => SIGNATURE_CAAB.to_vec(),
406            ESFSignature::CBAB => SIGNATURE_CBAB.to_vec(),
407            ESFSignature::CEAB => SIGNATURE_CEAB.to_vec(),
408            ESFSignature::CFAB => SIGNATURE_CFAB.to_vec(),
409        }
410    }
411}
412
413impl Decodeable for ESF {
414
415    fn decode<R: ReadBytes>(data: &mut R, _extra_data: &Option<DecodeableExtraData>) -> Result<Self> {
416        let mut esf = Self::default();
417
418        let sig_bytes = data.read_slice(4, false)?;
419        esf.signature = ESFSignature::try_from(sig_bytes.to_vec())?;
420
421        match esf.signature {
422            ESFSignature::CAAB => Self::read_caab(&mut esf, data)?,
423            ESFSignature::CBAB => Self::read_cbab(&mut esf, data)?,
424            _ => return Err(RLibError::DecodingESFUnsupportedSignature(sig_bytes[0], sig_bytes[1])),
425        };
426
427        // Debugging code.
428        //use std::io::Write;
429        //let mut x = std::fs::File::create("ceo.json")?;
430        //x.write_all(&serde_json::to_string_pretty(&esf).unwrap().as_bytes())?;
431
432        Ok(esf)
433    }
434}
435
436impl Encodeable for ESF {
437
438    fn encode<W: WriteBytes>(&mut self, buffer: &mut W, extra_data: &Option<EncodeableExtraData>) -> Result<()> {
439        let sig_bytes: Vec<u8> = Vec::from(self.signature);
440        buffer.write_all(&sig_bytes)?;
441
442        match self.signature {
443            ESFSignature::CAAB => self.save_caab(buffer, extra_data),
444            ESFSignature::CBAB => self.save_cbab(buffer, extra_data),
445            _ => Err(RLibError::EncodingESFUnsupportedSignature(self.signature.to_string())),
446        }
447    }
448}