mirror of
https://github.com/lifegpc/msg-tool.git
synced 2026-06-18 00:45:08 +08:00
WIP: Entis GLS CSX v2
This commit is contained in:
@@ -65,7 +65,12 @@ struct DataArea {
|
||||
}
|
||||
|
||||
impl StructUnpack for DataArea {
|
||||
fn unpack<R: Read + Seek>(reader: &mut R, big: bool, encoding: Encoding) -> Result<Self> {
|
||||
fn unpack<R: Read + Seek>(
|
||||
reader: &mut R,
|
||||
big: bool,
|
||||
encoding: Encoding,
|
||||
info: &Option<Box<dyn std::any::Any>>,
|
||||
) -> Result<Self> {
|
||||
reader.align(4)?;
|
||||
let start_loc = reader.stream_position()?;
|
||||
let mut data_tag = [0; 4];
|
||||
@@ -73,23 +78,23 @@ impl StructUnpack for DataArea {
|
||||
if &data_tag != b"DATA" {
|
||||
return Err(anyhow::anyhow!("Invalid DATA tag"));
|
||||
}
|
||||
let data_size = u32::unpack(reader, big, encoding)?;
|
||||
let count = u32::unpack(reader, big, encoding)? as usize;
|
||||
let data_size = u32::unpack(reader, big, encoding, info)?;
|
||||
let count = u32::unpack(reader, big, encoding, info)? as usize;
|
||||
let byte_array = reader.read_exact_vec(count)?;
|
||||
reader.align(4)?;
|
||||
let short_count = u32::unpack(reader, big, encoding)? as usize;
|
||||
let short_array = reader.read_struct_vec(short_count, big, encoding)?;
|
||||
let short_count = u32::unpack(reader, big, encoding, info)? as usize;
|
||||
let short_array = reader.read_struct_vec(short_count, big, encoding, info)?;
|
||||
reader.align(4)?;
|
||||
let long_count = u32::unpack(reader, big, encoding)? as usize;
|
||||
let long_array = reader.read_struct_vec(long_count, big, encoding)?;
|
||||
let longlong_count = u32::unpack(reader, big, encoding)? as usize;
|
||||
let longlong_array = reader.read_struct_vec(longlong_count, big, encoding)?;
|
||||
let double_count = u32::unpack(reader, big, encoding)? as usize;
|
||||
let double_array = reader.read_struct_vec(double_count, big, encoding)?;
|
||||
let str_count = u32::unpack(reader, big, encoding)? as usize;
|
||||
let long_count = u32::unpack(reader, big, encoding, info)? as usize;
|
||||
let long_array = reader.read_struct_vec(long_count, big, encoding, info)?;
|
||||
let longlong_count = u32::unpack(reader, big, encoding, info)? as usize;
|
||||
let longlong_array = reader.read_struct_vec(longlong_count, big, encoding, info)?;
|
||||
let double_count = u32::unpack(reader, big, encoding, info)? as usize;
|
||||
let double_array = reader.read_struct_vec(double_count, big, encoding, info)?;
|
||||
let str_count = u32::unpack(reader, big, encoding, info)? as usize;
|
||||
let mut string_array = Vec::with_capacity(str_count);
|
||||
for _ in 0..str_count {
|
||||
let str_len = u32::unpack(reader, big, encoding)? as usize;
|
||||
let str_len = u32::unpack(reader, big, encoding, info)? as usize;
|
||||
let str_bytes = reader.read_exact_vec(if encoding.is_utf16le() {
|
||||
str_len * 2
|
||||
} else {
|
||||
@@ -99,10 +104,10 @@ impl StructUnpack for DataArea {
|
||||
reader.align(4)?;
|
||||
string_array.push(s);
|
||||
}
|
||||
let octet_count = u32::unpack(reader, big, encoding)? as usize;
|
||||
let octet_count = u32::unpack(reader, big, encoding, info)? as usize;
|
||||
let mut octet_array = Vec::with_capacity(octet_count);
|
||||
for _ in 0..octet_count {
|
||||
let octet_len = u32::unpack(reader, big, encoding)? as usize;
|
||||
let octet_len = u32::unpack(reader, big, encoding, info)? as usize;
|
||||
let octet_bytes = reader.read_exact_vec(octet_len)?;
|
||||
reader.align(4)?;
|
||||
octet_array.push(octet_bytes);
|
||||
@@ -128,30 +133,36 @@ impl StructUnpack for DataArea {
|
||||
}
|
||||
|
||||
impl StructPack for DataArea {
|
||||
fn pack<W: Write>(&self, writer: &mut W, big: bool, encoding: Encoding) -> Result<()> {
|
||||
fn pack<W: Write>(
|
||||
&self,
|
||||
writer: &mut W,
|
||||
big: bool,
|
||||
encoding: Encoding,
|
||||
info: &Option<Box<dyn std::any::Any>>,
|
||||
) -> Result<()> {
|
||||
writer.write_all(b"DATA")?;
|
||||
let mut tmp = MemWriter::new();
|
||||
tmp.write_struct(&(self.byte_array.len() as u32), big, encoding)?;
|
||||
tmp.write_struct(&(self.byte_array.len() as u32), big, encoding, info)?;
|
||||
tmp.write_all(&self.byte_array)?;
|
||||
tmp.align(4)?;
|
||||
tmp.write_struct(&(self.short_array.len() as u32), big, encoding)?;
|
||||
tmp.write_struct(&(self.short_array.len() as u32), big, encoding, info)?;
|
||||
for v in &self.short_array {
|
||||
tmp.write_struct(v, big, encoding)?;
|
||||
tmp.write_struct(v, big, encoding, info)?;
|
||||
}
|
||||
tmp.align(4)?;
|
||||
tmp.write_struct(&(self.long_array.len() as u32), big, encoding)?;
|
||||
tmp.write_struct(&(self.long_array.len() as u32), big, encoding, info)?;
|
||||
for v in &self.long_array {
|
||||
tmp.write_struct(v, big, encoding)?;
|
||||
tmp.write_struct(v, big, encoding, info)?;
|
||||
}
|
||||
tmp.write_struct(&(self.longlong_array.len() as u32), big, encoding)?;
|
||||
tmp.write_struct(&(self.longlong_array.len() as u32), big, encoding, info)?;
|
||||
for v in &self.longlong_array {
|
||||
tmp.write_struct(v, big, encoding)?;
|
||||
tmp.write_struct(v, big, encoding, info)?;
|
||||
}
|
||||
tmp.write_struct(&(self.double_array.len() as u32), big, encoding)?;
|
||||
tmp.write_struct(&(self.double_array.len() as u32), big, encoding, info)?;
|
||||
for v in &self.double_array {
|
||||
tmp.write_struct(v, big, encoding)?;
|
||||
tmp.write_struct(v, big, encoding, info)?;
|
||||
}
|
||||
tmp.write_struct(&(self.string_array.len() as u32), big, encoding)?;
|
||||
tmp.write_struct(&(self.string_array.len() as u32), big, encoding, info)?;
|
||||
for s in &self.string_array {
|
||||
let encoded = encode_string(encoding, s, false)?;
|
||||
let str_len = if encoding.is_utf16le() {
|
||||
@@ -159,20 +170,20 @@ impl StructPack for DataArea {
|
||||
} else {
|
||||
encoded.len()
|
||||
};
|
||||
tmp.write_struct(&(str_len as u32), big, encoding)?;
|
||||
tmp.write_struct(&(str_len as u32), big, encoding, info)?;
|
||||
tmp.write_all(&encoded)?;
|
||||
tmp.align(4)?;
|
||||
}
|
||||
tmp.write_struct(&(self.octet_array.len() as u32), big, encoding)?;
|
||||
tmp.write_struct(&(self.octet_array.len() as u32), big, encoding, info)?;
|
||||
for o in &self.octet_array {
|
||||
tmp.write_struct(&(o.len() as u32), big, encoding)?;
|
||||
tmp.write_struct(&(o.len() as u32), big, encoding, info)?;
|
||||
tmp.write_all(o)?;
|
||||
tmp.align(4)?;
|
||||
}
|
||||
// make sure final size is aligned to 4 bytes
|
||||
tmp.data.resize(tmp.pos, 0);
|
||||
let data = tmp.into_inner();
|
||||
writer.write_struct(&(data.len() as u32 + 8), big, encoding)?;
|
||||
writer.write_struct(&(data.len() as u32 + 8), big, encoding, info)?;
|
||||
writer.write_all(&data)?;
|
||||
Ok(())
|
||||
}
|
||||
@@ -200,7 +211,7 @@ impl Tjs2 {
|
||||
return Err(anyhow::anyhow!("Invalid TJS2 header: {:?}", &header));
|
||||
}
|
||||
let _file_size = reader.read_u32()?;
|
||||
let data_area = DataArea::unpack(&mut reader, false, encoding)?;
|
||||
let data_area = DataArea::unpack(&mut reader, false, encoding, &None)?;
|
||||
let mut remaing = Vec::new();
|
||||
reader.read_to_end(&mut remaing)?;
|
||||
Ok(Self {
|
||||
@@ -262,7 +273,7 @@ impl Script for Tjs2 {
|
||||
.collect();
|
||||
file.write_all(b"TJS2100\0")?;
|
||||
file.write_u32(0)?; // placeholder for file size
|
||||
data_area.pack(&mut file, false, encoding)?;
|
||||
data_area.pack(&mut file, false, encoding, &None)?;
|
||||
file.write_all(&self.remaing)?;
|
||||
let file_size = file.stream_length()?;
|
||||
file.write_u32_at(8, file_size as u32)?; // write actual file size
|
||||
@@ -297,7 +308,7 @@ impl Script for Tjs2 {
|
||||
};
|
||||
file.write_all(b"TJS2100\0")?;
|
||||
file.write_u32(0)?; // placeholder for file size
|
||||
data_area.pack(&mut file, false, encoding)?;
|
||||
data_area.pack(&mut file, false, encoding, &None)?;
|
||||
file.write_all(&self.remaing)?;
|
||||
let file_size = file.stream_length()?;
|
||||
file.write_u32_at(8, file_size as u32)?; // write actual file size
|
||||
|
||||
@@ -81,7 +81,7 @@ impl ScriptBuilder for TjsNs0Builder {
|
||||
iv_len: 0,
|
||||
};
|
||||
let mut checker = ByteChecker::new(header.seed);
|
||||
header.pack(&mut writer, false, encoding)?;
|
||||
header.pack(&mut writer, false, encoding, &None)?;
|
||||
data.pack(&mut checker, &mut writer, false, encoding)?;
|
||||
let checksum = checker.final_check();
|
||||
writer.write_u32(checksum)?;
|
||||
@@ -102,7 +102,7 @@ enum TjsValue {
|
||||
}
|
||||
|
||||
fn unpack_string<R: Read + Seek>(reader: &mut R, big: bool, encoding: Encoding) -> Result<String> {
|
||||
let len = u32::unpack(reader, big, encoding)? as usize;
|
||||
let len = u32::unpack(reader, big, encoding, &None)? as usize;
|
||||
let tlen = if encoding.is_utf16le() { len * 2 } else { len };
|
||||
let mut buf = vec![0u8; tlen];
|
||||
reader.read_exact(&mut buf)?;
|
||||
@@ -117,7 +117,7 @@ fn pack_string<W: Write>(s: &str, writer: &mut W, big: bool, encoding: Encoding)
|
||||
} else {
|
||||
encoded.len() as u32
|
||||
};
|
||||
len.pack(writer, big, encoding)?;
|
||||
len.pack(writer, big, encoding, &None)?;
|
||||
writer.write_all(&encoded)?;
|
||||
Ok(())
|
||||
}
|
||||
@@ -135,36 +135,36 @@ impl TjsValue {
|
||||
let typ_byte = 0;
|
||||
let check_byte = checker.get_seed(typ_byte);
|
||||
let typ = ((check_byte as u16) << 8) | (typ_byte as u16);
|
||||
typ.pack(writer, big, encoding)?;
|
||||
typ.pack(writer, big, encoding, &None)?;
|
||||
}
|
||||
Self::Str(s) => {
|
||||
let typ_byte = 2;
|
||||
let check_byte = checker.get_seed(typ_byte);
|
||||
let typ = ((check_byte as u16) << 8) | (typ_byte as u16);
|
||||
typ.pack(writer, big, encoding)?;
|
||||
typ.pack(writer, big, encoding, &None)?;
|
||||
pack_string(s, writer, big, encoding)?;
|
||||
}
|
||||
Self::Int(i) => {
|
||||
let typ_byte = 4;
|
||||
let check_byte = checker.get_seed(typ_byte);
|
||||
let typ = ((check_byte as u16) << 8) | (typ_byte as u16);
|
||||
typ.pack(writer, big, encoding)?;
|
||||
i.pack(writer, big, encoding)?;
|
||||
typ.pack(writer, big, encoding, &None)?;
|
||||
i.pack(writer, big, encoding, &None)?;
|
||||
}
|
||||
Self::Double(f) => {
|
||||
let typ_byte = 5;
|
||||
let check_byte = checker.get_seed(typ_byte);
|
||||
let typ = ((check_byte as u16) << 8) | (typ_byte as u16);
|
||||
typ.pack(writer, big, encoding)?;
|
||||
f.pack(writer, big, encoding)?;
|
||||
typ.pack(writer, big, encoding, &None)?;
|
||||
f.pack(writer, big, encoding, &None)?;
|
||||
}
|
||||
Self::Array(arr) => {
|
||||
let typ_byte = 0x81;
|
||||
let check_byte = checker.get_seed(typ_byte);
|
||||
let typ = ((check_byte as u16) << 8) | (typ_byte as u16);
|
||||
typ.pack(writer, big, encoding)?;
|
||||
typ.pack(writer, big, encoding, &None)?;
|
||||
let arr_len = arr.len() as u32;
|
||||
arr_len.pack(writer, big, encoding)?;
|
||||
arr_len.pack(writer, big, encoding, &None)?;
|
||||
for item in arr {
|
||||
item.pack(checker, writer, big, encoding)?;
|
||||
}
|
||||
@@ -173,9 +173,9 @@ impl TjsValue {
|
||||
let typ_byte = 0xC1;
|
||||
let check_byte = checker.get_seed(typ_byte);
|
||||
let typ = ((check_byte as u16) << 8) | (typ_byte as u16);
|
||||
typ.pack(writer, big, encoding)?;
|
||||
typ.pack(writer, big, encoding, &None)?;
|
||||
let dict_len = dict.len() as u32;
|
||||
dict_len.pack(writer, big, encoding)?;
|
||||
dict_len.pack(writer, big, encoding, &None)?;
|
||||
for (key, value) in dict {
|
||||
pack_string(key, writer, big, encoding)?;
|
||||
value.pack(checker, writer, big, encoding)?;
|
||||
@@ -191,7 +191,7 @@ impl TjsValue {
|
||||
big: bool,
|
||||
encoding: Encoding,
|
||||
) -> Result<Self> {
|
||||
let typ = u16::unpack(reader, big, encoding)?;
|
||||
let typ = u16::unpack(reader, big, encoding, &None)?;
|
||||
let typ_byte = (typ & 0xff) as u8;
|
||||
let check_byte = (typ >> 8) as u8;
|
||||
let expected_check = checker.get_seed(typ_byte);
|
||||
@@ -206,10 +206,10 @@ impl TjsValue {
|
||||
Ok(match typ_byte {
|
||||
0 => TjsValue::Void(()),
|
||||
2 => TjsValue::Str(unpack_string(reader, big, encoding)?),
|
||||
4 => TjsValue::Int(i64::unpack(reader, big, encoding)?),
|
||||
5 => TjsValue::Double(f64::unpack(reader, big, encoding)?),
|
||||
4 => TjsValue::Int(i64::unpack(reader, big, encoding, &None)?),
|
||||
5 => TjsValue::Double(f64::unpack(reader, big, encoding, &None)?),
|
||||
0x81 => {
|
||||
let arr_len = u32::unpack(reader, big, encoding)? as usize;
|
||||
let arr_len = u32::unpack(reader, big, encoding, &None)? as usize;
|
||||
let mut arr = Vec::with_capacity(arr_len);
|
||||
for _ in 0..arr_len {
|
||||
arr.push(TjsValue::unpack(checker, reader, big, encoding)?);
|
||||
@@ -217,7 +217,7 @@ impl TjsValue {
|
||||
TjsValue::Array(arr)
|
||||
}
|
||||
0xC1 => {
|
||||
let kv_len = u32::unpack(reader, big, encoding)? as usize;
|
||||
let kv_len = u32::unpack(reader, big, encoding, &None)? as usize;
|
||||
let mut dict = BTreeMap::new();
|
||||
for _ in 0..kv_len {
|
||||
let key = unpack_string(reader, big, encoding)?;
|
||||
@@ -315,7 +315,7 @@ impl TjsNs0 {
|
||||
config: &ExtraConfig,
|
||||
) -> Result<Self> {
|
||||
let mut reader = MemReader::new(buf);
|
||||
let header = Header::unpack(&mut reader, false, encoding)?;
|
||||
let header = Header::unpack(&mut reader, false, encoding, &None)?;
|
||||
if &header.magic != b"TJS/" {
|
||||
return Err(anyhow::anyhow!("Not a valid TJS/ns0 file"));
|
||||
}
|
||||
@@ -405,7 +405,7 @@ impl Script for TjsNs0 {
|
||||
let mut header = self.header.clone();
|
||||
header.check = *b"ns0\0";
|
||||
let mut checker = ByteChecker::new(header.seed);
|
||||
header.pack(&mut file, false, encoding)?;
|
||||
header.pack(&mut file, false, encoding, &None)?;
|
||||
data.pack(&mut checker, &mut file, false, encoding)?;
|
||||
let checksum = checker.final_check();
|
||||
file.write_u32(checksum)?;
|
||||
|
||||
Reference in New Issue
Block a user