Skip to content

Commit

Permalink
Merge branch 'hotfix/v0.3.1'
Browse files Browse the repository at this point in the history
  • Loading branch information
Frodo45127 committed Jan 9, 2018
2 parents ca050a7 + 4e13cd9 commit a91dea7
Show file tree
Hide file tree
Showing 4 changed files with 182 additions and 62 deletions.
94 changes: 94 additions & 0 deletions src/common/coding_helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,65 @@ pub fn decode_packedfile_optional_string_u8(packed_file_data: Vec<u8>, index: us
}
}

/// This function allow us to decode an UTF-16 encoded string cell. We return the string and the
/// index for the next cell's data.
#[allow(dead_code)]
pub fn decode_packedfile_string_u16(packed_file_data: Vec<u8>, index: usize) -> Result<(String, usize), Error> {
if packed_file_data.len() >= 2 {
match decode_packedfile_integer_u16(packed_file_data[..2].to_vec(), index) {
Ok(result) => {
let size = result.0 * 2;
let mut index = result.1;
if packed_file_data.len() >= size as usize {
match decode_string_u16(packed_file_data[2..(2 + size as usize)].to_vec()) {
Ok(string) => {
index += size as usize;
Ok((string, index))
}
Err(error) => Err(error)
}
}
else {
return Err(Error::new(ErrorKind::Other, format!("Error decoding an u8 String: Index \"{}\" out of bounds (Max length: {}).", index, packed_file_data.len())))
}
}
Err(error) => Err(error)
}
}
else {
return Err(Error::new(ErrorKind::Other, format!("Error decoding an u16 (String size): Index \"{}\" out of bounds (Max length: {}).", index, packed_file_data.len())))
}
}

/// This function allow us to decode an UTF-16 encoded optional string cell. We return the string (or
/// an empty string if it doesn't exist) and the index for the next cell's data.
///
/// NOTE: These strings's first byte it's a boolean that indicates if the string has something.
#[allow(dead_code)]
pub fn decode_packedfile_optional_string_u16(packed_file_data: Vec<u8>, index: usize) -> Result<(String, usize), Error> {
if packed_file_data.len() >= 1 {
match decode_packedfile_bool(packed_file_data[0], index) {
Ok(result) => {
let exist = result.0;
let index = result.1;
if exist {
match decode_packedfile_string_u16(packed_file_data[1..].to_vec(), index) {
Ok(result) => Ok(result),
Err(error) => Err(Error::new(ErrorKind::Other, error::Error::description(&error).to_string())),
}
}
else {
Ok((String::new(), result.1))
}
}
Err(error) => Err(error)
}
}
else {
return Err(Error::new(ErrorKind::Other, format!("Error decoding an u8 Optional String: Index \"{}\" out of bounds (Max length: {}).", index, packed_file_data.len())))
}
}

/// This function allow us to decode a boolean cell. We return the boolean's value and the index
/// for the next cell's data.
#[allow(dead_code)]
Expand Down Expand Up @@ -391,6 +450,41 @@ pub fn encode_packedfile_optional_string_u8(optional_string_u8_decoded: String)
optional_string_u8_encoded
}

/// This function allow us to encode an UTF-16 decoded string cell. We return the Vec<u8> of
/// the encoded string.
#[allow(dead_code)]
pub fn encode_packedfile_string_u16(string_u16_decoded: String) -> Vec<u8> {
let mut string_u16_encoded = vec![];
let mut string_u16_data = encode_string_u16(string_u16_decoded);
//let mut string_u16_lenght = encode_integer_u16(string_u16_data.len() as u16);

//string_u16_encoded.append(&mut string_u16_lenght);
string_u16_encoded.append(&mut string_u16_data);

string_u16_encoded
}

/// This function allow us to encode an UTF-8 decoded string cell. We return the Vec<u8> of
/// the encoded string.
#[allow(dead_code)]
pub fn encode_packedfile_optional_string_u16(optional_string_u16_decoded: String) -> Vec<u8> {
let mut optional_string_u16_encoded = vec![];

if optional_string_u16_decoded.is_empty() {
optional_string_u16_encoded.append(&mut encode_bool(false));
}
else {
let mut optional_string_u16_data = encode_string_u16(optional_string_u16_decoded);
//let mut optional_string_u16_lenght = encode_integer_u16(optional_string_u16_data.len() as u16);

optional_string_u16_encoded.append(&mut encode_bool(true));
//optional_string_u16_encoded.append(&mut optional_string_u16_lenght);
optional_string_u16_encoded.append(&mut optional_string_u16_data);
}

optional_string_u16_encoded
}

/// This function allow us to encode to Vec<u8> a boolean cell. We return the Vec<u8>.
#[allow(dead_code)]
pub fn encode_packedfile_bool(bool_decoded: bool) -> Vec<u8> {
Expand Down
6 changes: 4 additions & 2 deletions src/packedfile/db/master_schema.xml
Original file line number Diff line number Diff line change
Expand Up @@ -19564,8 +19564,9 @@
</table>
<table table_name='technology_effects_junction_tables'
table_version='0' >
<field fkey='technologies_tables.key' name='technology' type='string' pk='true' />
<field fkey='effects_tables.effect' name='effect' type='string' pk='true' />
<field fkey='technologies_tables.key' name='technology' type='string_ascii' pk='true' />
<field fkey='effects_tables.effect' name='effect' type='string_ascii' pk='true' />
<field fkey='campaign_effect_scopes_tables.key' name='effect_scope' type='string_ascii' />
<field name='value' type='float' />
</table>
<table table_name='technology_effects_junction_tables'
Expand Down Expand Up @@ -19688,6 +19689,7 @@
<field name='research_points_required' type='int' />
<field name='cost_per_round' type='int' />
<field name='food_cost' type='int' />
<field name='unknown' type='optstring_ascii' />
</table>
<table table_name='technology_nodes_tables'
table_version='2' >
Expand Down
122 changes: 68 additions & 54 deletions src/packedfile/db/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ pub struct DB {
/// - packed_file_header_packed_file_entry_count:
#[derive(Clone, Debug)]
pub struct DBHeader {
pub packed_file_header_packed_file_guid: String,
pub packed_file_header_packed_file_guid: (String, usize),
pub packed_file_header_packed_file_version: u32,
pub packed_file_header_packed_file_version_marker: bool,
pub packed_file_header_packed_file_mysterious_byte: u8,
Expand All @@ -63,8 +63,10 @@ pub struct DBData {
pub enum DecodedData {
Index(String),
Boolean(bool),
String(String),
OptionalString(String),
StringU8(String),
StringU16(String),
OptionalStringU8(String),
OptionalStringU16(String),
Integer(u32),
Float(f32),
RawData(Vec<u8>)
Expand Down Expand Up @@ -104,11 +106,7 @@ impl DB {
/// It returns a Vec<u8> with the entire DB encoded in it.
pub fn save(packed_file_decoded: &DB) -> Result<Vec<u8>, Error> {

let mut packed_file_data_encoded = match DBData::save(&packed_file_decoded.packed_file_data) {
Ok(data) => data,
Err(error) => return Err(error)
};

let mut packed_file_data_encoded = DBData::save(&packed_file_decoded.packed_file_data)?;
let mut packed_file_header_encoded = DBHeader::save(&packed_file_decoded.packed_file_header, packed_file_data_encoded.1);

let mut packed_file_encoded: Vec<u8> = vec![];
Expand All @@ -122,63 +120,52 @@ impl DB {
/// Implementation of "DBHeader"
impl DBHeader {

/// This function creates a new DBHeader from nothing.
pub fn new() -> DBHeader {
let packed_file_header_packed_file_guid = (String::new(), 0);
let packed_file_header_packed_file_version = 0;
let packed_file_header_packed_file_version_marker = false;
let packed_file_header_packed_file_mysterious_byte = 0;
let packed_file_header_packed_file_entry_count = 0;

DBHeader {
packed_file_header_packed_file_guid,
packed_file_header_packed_file_version,
packed_file_header_packed_file_version_marker,
packed_file_header_packed_file_mysterious_byte,
packed_file_header_packed_file_entry_count,
}
}

/// This function creates a decoded DBHeader from a encoded PackedFile. It also return an index,
/// to know where the body starts.
pub fn read(packed_file_header: Vec<u8>) -> Result<(DBHeader, usize), Error> {

let mut packed_file_header_decoded = DBHeader::new();
let mut index: usize = 0;
let packed_file_header_packed_file_guid: String;
let packed_file_header_packed_file_version: u32;
let packed_file_header_packed_file_version_marker: bool;

// If it has a GUID_MARKER, we get the GUID.
if &packed_file_header[index..(index + 4)] == GUID_MARKER {
let packed_file_header_guid_lenght = match coding_helpers::decode_integer_u16(packed_file_header[4..6].to_vec()) {
Ok(data) => data * 2,
Err(error) => return Err(error)
};
packed_file_header_packed_file_guid = match coding_helpers::decode_string_u16(packed_file_header[6..(6 + (packed_file_header_guid_lenght as usize))].to_vec()){
Ok(data) => data,
Err(error) => return Err(error)
};
index = 6 + packed_file_header_guid_lenght as usize;
}
else {
packed_file_header_packed_file_guid = String::new();
index += 4;
packed_file_header_decoded.packed_file_header_packed_file_guid = coding_helpers::decode_packedfile_string_u16(packed_file_header[index..].to_vec(), index)?;
index = packed_file_header_decoded.packed_file_header_packed_file_guid.1;
}

// If it has a VERSION_MARKER, we get the version of the table.
if &packed_file_header[index..(index + 4)] == VERSION_MARKER {
packed_file_header_packed_file_version = match coding_helpers::decode_integer_u32(packed_file_header[(index + 4)..(index + 8)].to_vec()) {
Ok(data) => data,
Err(error) => return Err(error)
};
packed_file_header_packed_file_version_marker = true;
packed_file_header_decoded.packed_file_header_packed_file_version = coding_helpers::decode_integer_u32(packed_file_header[(index + 4)..(index + 8)].to_vec())?;
packed_file_header_decoded.packed_file_header_packed_file_version_marker = true;
index = index + 8;
}
else {
packed_file_header_packed_file_version = 0;
packed_file_header_packed_file_version_marker = false;
}

// We save a mysterious byte I don't know what it does.
let packed_file_header_packed_file_mysterious_byte = packed_file_header[index];
packed_file_header_decoded.packed_file_header_packed_file_mysterious_byte = packed_file_header[index];
index += 1;

let packed_file_header_packed_file_entry_count = match coding_helpers::decode_integer_u32(packed_file_header[(index)..(index + 4)].to_vec()) {
Ok(data) => data,
Err(error) => return Err(error)
};

packed_file_header_decoded.packed_file_header_packed_file_entry_count = coding_helpers::decode_integer_u32(packed_file_header[(index)..(index + 4)].to_vec())?;
index += 4;

Ok((DBHeader {
packed_file_header_packed_file_guid,
packed_file_header_packed_file_version,
packed_file_header_packed_file_version_marker,
packed_file_header_packed_file_mysterious_byte,
packed_file_header_packed_file_entry_count,
},
index))
Ok((packed_file_header_decoded, index))
}


Expand All @@ -188,7 +175,7 @@ impl DBHeader {
let mut packed_file_header_encoded: Vec<u8> = vec![];

// First we get the lenght of the GUID (u16 reversed) and the GUID, in a u16 string.
let guid_encoded = coding_helpers::encode_string_u16(packed_file_header_decoded.packed_file_header_packed_file_guid.clone());
let guid_encoded = coding_helpers::encode_string_u16(packed_file_header_decoded.packed_file_header_packed_file_guid.0.clone());

packed_file_header_encoded.extend_from_slice(&GUID_MARKER);
packed_file_header_encoded.extend_from_slice(&guid_encoded);
Expand Down Expand Up @@ -325,7 +312,8 @@ impl DBData {
// The rest of the columns, we decode them based on his type and store them in a DecodedData
// enum, as enums are the only thing I found that can store them
//
// NOTE: string/optstring and string_ascii/optstring_ascii are the same thing.
// NOTE: string => u16.
// string_ascii => u8.
else {
let field = packed_file_data_entries_fields.get_index((column as usize) - 1).unwrap();
let field_type = field.1;
Expand All @@ -340,20 +328,38 @@ impl DBData {
Err(error) => return Err(error)
};
}
"string" | "string_ascii" => {
"string" => {
match coding_helpers::decode_packedfile_string_u16(packed_file_data[index..].to_vec(), index) {
Ok(data) => {
index = data.1;
entry.push(DecodedData::StringU16(data.0));
}
Err(error) => return Err(error)
};
}
"string_ascii" => {
match coding_helpers::decode_packedfile_string_u8(packed_file_data[index..].to_vec(), index) {
Ok(data) => {
index = data.1;
entry.push(DecodedData::String(data.0));
entry.push(DecodedData::StringU8(data.0));
}
Err(error) => return Err(error)
};
}
"optstring" => {
match coding_helpers::decode_packedfile_optional_string_u16(packed_file_data[index..].to_vec(), index) {
Ok(data) => {
index = data.1;
entry.push(DecodedData::OptionalStringU16(data.0));
}
Err(error) => return Err(error)
};
}
"optstring" | "optstring_ascii" => {
"optstring_ascii" => {
match coding_helpers::decode_packedfile_optional_string_u8(packed_file_data[index..].to_vec(), index) {
Ok(data) => {
index = data.1;
entry.push(DecodedData::OptionalString(data.0));
entry.push(DecodedData::OptionalStringU8(data.0));
}
Err(error) => return Err(error)
};
Expand Down Expand Up @@ -428,14 +434,22 @@ impl DBData {
let mut encoded_data = coding_helpers::encode_packedfile_bool(data.clone());
packed_file_data_encoded.append(&mut encoded_data);
},
DecodedData::String(ref data) => {
DecodedData::StringU8(ref data) => {
let mut encoded_data = coding_helpers::encode_packedfile_string_u8(data.clone());
packed_file_data_encoded.append(&mut encoded_data);
},
DecodedData::OptionalString(ref data) => {
DecodedData::StringU16(ref data) => {
let mut encoded_data = coding_helpers::encode_packedfile_string_u16(data.clone());
packed_file_data_encoded.append(&mut encoded_data);
},
DecodedData::OptionalStringU8(ref data) => {
let mut encoded_data = coding_helpers::encode_packedfile_optional_string_u8(data.clone());
packed_file_data_encoded.append(&mut encoded_data);
},
DecodedData::OptionalStringU16(ref data) => {
let mut encoded_data = coding_helpers::encode_packedfile_optional_string_u16(data.clone());
packed_file_data_encoded.append(&mut encoded_data);
},
DecodedData::Integer(data) => {
let mut encoded_data = coding_helpers::encode_packedfile_integer_u32(data.clone());
packed_file_data_encoded.append(&mut encoded_data);
Expand Down
Loading

0 comments on commit a91dea7

Please sign in to comment.