mirror of
https://github.com/lifegpc/msg-tool.git
synced 2026-06-19 01:14:45 +08:00
WIP: Entis GLS CSX v2
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
//! Original license: GPL-3.0
|
||||
mod base;
|
||||
mod v1;
|
||||
mod v2;
|
||||
|
||||
use crate::ext::io::*;
|
||||
use crate::scripts::base::*;
|
||||
@@ -12,6 +13,7 @@ use crate::utils::encoding::*;
|
||||
use anyhow::Result;
|
||||
use base::ECSImage;
|
||||
use v1::ECSExecutionImageV1;
|
||||
use v2::ECSExecutionImageV2;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct CSXScriptBuilder {}
|
||||
@@ -66,9 +68,15 @@ pub struct CSXScript {
|
||||
impl CSXScript {
|
||||
pub fn new(buf: Vec<u8>, config: &ExtraConfig) -> Result<Self> {
|
||||
let reader = MemReader::new(buf);
|
||||
let img = ECSExecutionImageV1::new(reader.to_ref(), config)?;
|
||||
let img = {
|
||||
match ECSExecutionImageV1::new(reader.to_ref(), config) {
|
||||
Ok(img) => Box::new(img),
|
||||
Err(_) => Box::new(ECSExecutionImageV2::new(reader.to_ref(), config)?)
|
||||
as Box<dyn ECSImage>,
|
||||
}
|
||||
};
|
||||
Ok(Self {
|
||||
img: Box::new(img),
|
||||
img,
|
||||
disasm: config.entis_gls_csx_disasm,
|
||||
custom_yaml: config.custom_yaml,
|
||||
})
|
||||
|
||||
@@ -128,7 +128,7 @@ impl<'a> ECSExecutionImageDisassembler<'a> {
|
||||
let length = self.stream.read_u32()?;
|
||||
if length != 0x80000000 {
|
||||
self.stream.seek_relative(-4)?;
|
||||
let s = WideString::unpack(&mut self.stream, false, Encoding::Utf16LE)?.0;
|
||||
let s = WideString::unpack(&mut self.stream, false, Encoding::Utf16LE, &None)?.0;
|
||||
Ok((None, s))
|
||||
} else if let Some(conststr) = &self.conststr {
|
||||
let index = self.stream.read_u32()? as usize;
|
||||
|
||||
@@ -36,10 +36,10 @@ pub struct ECSExecutionImage {
|
||||
|
||||
impl ECSExecutionImage {
|
||||
pub fn new(mut reader: MemReaderRef<'_>, config: &ExtraConfig) -> Result<Self> {
|
||||
let file_header = EMCFileHeader::unpack(&mut reader, false, Encoding::Utf8)?;
|
||||
// if file_header.signagure != *b"Entis\x1a\0\0" {
|
||||
// return Err(anyhow::anyhow!("Invalid EMC file signature"));
|
||||
// }
|
||||
let file_header = EMCFileHeader::unpack(&mut reader, false, Encoding::Utf8, &None)?;
|
||||
if file_header.signagure != *b"Entis\x1a\0\0" {
|
||||
return Err(anyhow::anyhow!("Invalid EMC file signature"));
|
||||
}
|
||||
let len = reader.data.len();
|
||||
let mut exi_header = None;
|
||||
let mut header = None;
|
||||
@@ -70,7 +70,7 @@ impl ECSExecutionImage {
|
||||
let buf = reader.read_exact_vec(size as usize)?;
|
||||
{
|
||||
let mut sread = MemReaderRef::new(&buf);
|
||||
header = Some(EXIHeader::unpack(&mut sread, false, Encoding::Utf8)?);
|
||||
header = Some(EXIHeader::unpack(&mut sread, false, Encoding::Utf8, &None)?);
|
||||
}
|
||||
exi_header = Some(buf);
|
||||
if let Some(hdr) = &header {
|
||||
@@ -85,12 +85,23 @@ impl ECSExecutionImage {
|
||||
}
|
||||
// function
|
||||
0x6E6F6974636E7566 => {
|
||||
pif_prologue = Some(DWordArray::unpack(&mut reader, false, Encoding::Utf8)?);
|
||||
pif_epilogue = Some(DWordArray::unpack(&mut reader, false, Encoding::Utf8)?);
|
||||
pif_prologue = Some(DWordArray::unpack(
|
||||
&mut reader,
|
||||
false,
|
||||
Encoding::Utf8,
|
||||
&None,
|
||||
)?);
|
||||
pif_epilogue = Some(DWordArray::unpack(
|
||||
&mut reader,
|
||||
false,
|
||||
Encoding::Utf8,
|
||||
&None,
|
||||
)?);
|
||||
function_list = Some(FunctionNameList::unpack(
|
||||
&mut reader,
|
||||
false,
|
||||
Encoding::Utf8,
|
||||
&None,
|
||||
)?);
|
||||
}
|
||||
// global
|
||||
@@ -98,7 +109,8 @@ impl ECSExecutionImage {
|
||||
let count = reader.read_u32()?;
|
||||
let mut items = Vec::with_capacity(count as usize);
|
||||
for _ in 0..count {
|
||||
let name = WideString::unpack(&mut reader, false, Encoding::Utf16LE)?.0;
|
||||
let name =
|
||||
WideString::unpack(&mut reader, false, Encoding::Utf16LE, &None)?.0;
|
||||
let obj = ECSObject::read_from(&mut reader, int64)?;
|
||||
items.push(ECSObjectItem { name, obj });
|
||||
}
|
||||
@@ -109,13 +121,19 @@ impl ECSExecutionImage {
|
||||
let count = reader.read_u32()?;
|
||||
let mut items = Vec::with_capacity(count as usize);
|
||||
for _ in 0..count {
|
||||
let name = WideString::unpack(&mut reader, false, Encoding::Utf16LE)?.0;
|
||||
let name =
|
||||
WideString::unpack(&mut reader, false, Encoding::Utf16LE, &None)?.0;
|
||||
let length = reader.read_i32()?;
|
||||
let obj = if length >= 0 {
|
||||
let mut datas = Vec::with_capacity(length as usize);
|
||||
for _ in 0..length {
|
||||
let name =
|
||||
WideString::unpack(&mut reader, false, Encoding::Utf16LE)?.0;
|
||||
let name = WideString::unpack(
|
||||
&mut reader,
|
||||
false,
|
||||
Encoding::Utf16LE,
|
||||
&None,
|
||||
)?
|
||||
.0;
|
||||
let obj = ECSObject::read_from(&mut reader, int64)?;
|
||||
datas.push(ECSObjectItem { name, obj });
|
||||
}
|
||||
@@ -133,16 +151,17 @@ impl ECSExecutionImage {
|
||||
&mut reader,
|
||||
false,
|
||||
Encoding::Utf8,
|
||||
&None,
|
||||
)?);
|
||||
}
|
||||
// linkinf
|
||||
0x20666E696B6E696C => {
|
||||
ext_global_ref = DWordArray::unpack(&mut reader, false, Encoding::Utf8)?;
|
||||
ext_data_ref = DWordArray::unpack(&mut reader, false, Encoding::Utf8)?;
|
||||
ext_global_ref = DWordArray::unpack(&mut reader, false, Encoding::Utf8, &None)?;
|
||||
ext_data_ref = DWordArray::unpack(&mut reader, false, Encoding::Utf8, &None)?;
|
||||
imp_global_ref =
|
||||
TaggedRefAddressList::unpack(&mut reader, false, Encoding::Utf8)?;
|
||||
TaggedRefAddressList::unpack(&mut reader, false, Encoding::Utf8, &None)?;
|
||||
imp_data_ref =
|
||||
TaggedRefAddressList::unpack(&mut reader, false, Encoding::Utf8)?;
|
||||
TaggedRefAddressList::unpack(&mut reader, false, Encoding::Utf8, &None)?;
|
||||
if !ext_global_ref.is_empty()
|
||||
|| !ext_data_ref.is_empty()
|
||||
|| !imp_global_ref.is_empty()
|
||||
@@ -286,7 +305,8 @@ impl ECSExecutionImage {
|
||||
}
|
||||
|
||||
fn save<'a>(&self, mut writer: Box<dyn Write + 'a>) -> Result<()> {
|
||||
self.file_header.pack(&mut writer, false, Encoding::Utf8)?;
|
||||
self.file_header
|
||||
.pack(&mut writer, false, Encoding::Utf8, &None)?;
|
||||
if let Some(exi_header) = &self.exi_header {
|
||||
writer.write_u64(0x2020726564616568)?; // header
|
||||
writer.write_u64(exi_header.len() as u64)?;
|
||||
@@ -297,9 +317,12 @@ impl ECSExecutionImage {
|
||||
writer.write_all(&self.image.data)?;
|
||||
writer.write_u64(0x6E6F6974636E7566)?; // function
|
||||
let mut mem = MemWriter::new();
|
||||
self.pif_prologue.pack(&mut mem, false, Encoding::Utf8)?;
|
||||
self.pif_epilogue.pack(&mut mem, false, Encoding::Utf8)?;
|
||||
self.function_list.pack(&mut mem, false, Encoding::Utf8)?;
|
||||
self.pif_prologue
|
||||
.pack(&mut mem, false, Encoding::Utf8, &None)?;
|
||||
self.pif_epilogue
|
||||
.pack(&mut mem, false, Encoding::Utf8, &None)?;
|
||||
self.function_list
|
||||
.pack(&mut mem, false, Encoding::Utf8, &None)?;
|
||||
let data = mem.into_inner();
|
||||
writer.write_u64(data.len() as u64)?;
|
||||
writer.write_all(&data)?;
|
||||
@@ -312,7 +335,7 @@ impl ECSExecutionImage {
|
||||
};
|
||||
mem.write_u32(self.csg_global.len() as u32)?;
|
||||
for item in self.csg_global.iter() {
|
||||
WideString(item.name.clone()).pack(&mut mem, false, Encoding::Utf16LE)?;
|
||||
WideString(item.name.clone()).pack(&mut mem, false, Encoding::Utf16LE, &None)?;
|
||||
item.obj.write_to(&mut mem, int64)?;
|
||||
}
|
||||
let data = mem.into_inner();
|
||||
@@ -322,7 +345,7 @@ impl ECSExecutionImage {
|
||||
let mut mem = MemWriter::new();
|
||||
mem.write_u32(self.csg_data.len() as u32)?;
|
||||
for item in self.csg_data.iter() {
|
||||
WideString(item.name.clone()).pack(&mut mem, false, Encoding::Utf16LE)?;
|
||||
WideString(item.name.clone()).pack(&mut mem, false, Encoding::Utf16LE, &None)?;
|
||||
match &item.obj {
|
||||
ECSObject::Global(g) => {
|
||||
mem.write_i32(g.len() as i32)?;
|
||||
@@ -331,6 +354,7 @@ impl ECSExecutionImage {
|
||||
&mut mem,
|
||||
false,
|
||||
Encoding::Utf16LE,
|
||||
&None,
|
||||
)?;
|
||||
data_item.obj.write_to(&mut mem, int64)?;
|
||||
}
|
||||
@@ -347,17 +371,21 @@ impl ECSExecutionImage {
|
||||
if let Some(ext_const_str) = &self.ext_const_str {
|
||||
writer.write_u64(0x72747374736E6F63)?; // conststr
|
||||
let mut mem = MemWriter::new();
|
||||
ext_const_str.pack(&mut mem, false, Encoding::Utf8)?;
|
||||
ext_const_str.pack(&mut mem, false, Encoding::Utf8, &None)?;
|
||||
let data = mem.into_inner();
|
||||
writer.write_u64(data.len() as u64)?;
|
||||
writer.write_all(&data)?;
|
||||
}
|
||||
writer.write_u64(0x20666E696B6E696C)?; // linkinf
|
||||
let mut mem = MemWriter::new();
|
||||
self.ext_global_ref.pack(&mut mem, false, Encoding::Utf8)?;
|
||||
self.ext_data_ref.pack(&mut mem, false, Encoding::Utf8)?;
|
||||
self.imp_global_ref.pack(&mut mem, false, Encoding::Utf8)?;
|
||||
self.imp_data_ref.pack(&mut mem, false, Encoding::Utf8)?;
|
||||
self.ext_global_ref
|
||||
.pack(&mut mem, false, Encoding::Utf8, &None)?;
|
||||
self.ext_data_ref
|
||||
.pack(&mut mem, false, Encoding::Utf8, &None)?;
|
||||
self.imp_global_ref
|
||||
.pack(&mut mem, false, Encoding::Utf8, &None)?;
|
||||
self.imp_data_ref
|
||||
.pack(&mut mem, false, Encoding::Utf8, &None)?;
|
||||
let data = mem.into_inner();
|
||||
writer.write_u64(data.len() as u64)?;
|
||||
writer.write_all(&data)?;
|
||||
@@ -402,7 +430,8 @@ impl ECSImage for ECSExecutionImage {
|
||||
disasm.stream.pos = cmd.addr as usize + 1;
|
||||
let _csom = disasm.read_csom()?;
|
||||
let num_args = disasm.stream.read_i32()?;
|
||||
let func_name = WideString::unpack(&mut disasm.stream, false, Encoding::Utf16LE)?.0;
|
||||
let func_name =
|
||||
WideString::unpack(&mut disasm.stream, false, Encoding::Utf16LE, &None)?.0;
|
||||
let mut is_mess = false;
|
||||
if num_args == 1 {
|
||||
if func_name == "SceneTitle" {
|
||||
@@ -492,7 +521,8 @@ impl ECSImage for ECSExecutionImage {
|
||||
disasm.stream.pos = cmd.addr as usize + 1;
|
||||
let csom = disasm.read_csom()?;
|
||||
let num_args = disasm.stream.read_i32()?;
|
||||
let func_name = WideString::unpack(&mut disasm.stream, false, Encoding::Utf16LE)?.0;
|
||||
let func_name =
|
||||
WideString::unpack(&mut disasm.stream, false, Encoding::Utf16LE, &None)?.0;
|
||||
let mut is_mess = false;
|
||||
if num_args == 1 {
|
||||
if func_name == "SceneTitle" {
|
||||
@@ -568,7 +598,8 @@ impl ECSImage for ECSExecutionImage {
|
||||
string_stack.clear();
|
||||
} else if is_enter {
|
||||
disasm.stream.pos = cmd.addr as usize + 1;
|
||||
let name = WideString::unpack(&mut disasm.stream, false, Encoding::Utf16LE)?.0;
|
||||
let name =
|
||||
WideString::unpack(&mut disasm.stream, false, Encoding::Utf16LE, &None)?.0;
|
||||
let num_args = disasm.stream.read_i32()?;
|
||||
if num_args == 0 {
|
||||
pre_enter_name = name.clone();
|
||||
@@ -630,7 +661,8 @@ impl ECSImage for ECSExecutionImage {
|
||||
disasm.stream.pos = cmd.addr as usize + 1;
|
||||
let csom = disasm.read_csom()?;
|
||||
let num_args = disasm.stream.read_i32()?;
|
||||
let func_name = WideString::unpack(&mut disasm.stream, false, Encoding::Utf16LE)?.0;
|
||||
let func_name =
|
||||
WideString::unpack(&mut disasm.stream, false, Encoding::Utf16LE, &None)?.0;
|
||||
let mut is_mess = false;
|
||||
if csom == CsomAuto && num_args == 1 && func_name == "Mess" {
|
||||
is_mess = true;
|
||||
@@ -718,7 +750,7 @@ impl ECSImage for ECSExecutionImage {
|
||||
new_image.write_u8(CsicLoad.into())?;
|
||||
new_image.write_u8(CsomImmediate.into())?;
|
||||
new_image.write_u8(CsvtString.into())?;
|
||||
WideString(mes).pack(&mut new_image, false, Encoding::Utf8)?;
|
||||
WideString(mes).pack(&mut new_image, false, Encoding::Utf8, &None)?;
|
||||
new_assembly.push(tcmd);
|
||||
let mut tcmd = if tmp_index <= post_index {
|
||||
let data = assembly[tmp_index].clone();
|
||||
@@ -746,6 +778,7 @@ impl ECSImage for ECSExecutionImage {
|
||||
&mut new_image,
|
||||
false,
|
||||
Encoding::Utf16LE,
|
||||
&None,
|
||||
)?;
|
||||
new_assembly.push(tcmd);
|
||||
let mut tcmd = if tmp_index <= post_index {
|
||||
@@ -825,7 +858,7 @@ impl ECSImage for ECSExecutionImage {
|
||||
new_image.write_u8(CsicLoad.into())?;
|
||||
new_image.write_u8(lcsom.into())?;
|
||||
new_image.write_u8(lcsvt.into())?;
|
||||
WideString(name).pack(&mut new_image, false, Encoding::Utf8)?;
|
||||
WideString(name).pack(&mut new_image, false, Encoding::Utf8, &None)?;
|
||||
dumped_index += 1;
|
||||
while dumped_index <= index {
|
||||
let tcmd = &mut assembly[dumped_index];
|
||||
@@ -886,7 +919,7 @@ impl ECSImage for ECSExecutionImage {
|
||||
new_image.write_u8(CsicLoad.into())?;
|
||||
new_image.write_u8(lcsom.into())?;
|
||||
new_image.write_u8(lcsvt.into())?;
|
||||
WideString(message).pack(&mut new_image, false, Encoding::Utf8)?;
|
||||
WideString(message).pack(&mut new_image, false, Encoding::Utf8, &None)?;
|
||||
dumped_index += 1;
|
||||
while dumped_index <= index {
|
||||
let tcmd = &mut assembly[dumped_index];
|
||||
@@ -947,7 +980,7 @@ impl ECSImage for ECSExecutionImage {
|
||||
new_image.write_u8(CsicLoad.into())?;
|
||||
new_image.write_u8(lcsom.into())?;
|
||||
new_image.write_u8(lcsvt.into())?;
|
||||
WideString(message).pack(&mut new_image, false, Encoding::Utf8)?;
|
||||
WideString(message).pack(&mut new_image, false, Encoding::Utf8, &None)?;
|
||||
dumped_index += 1;
|
||||
while dumped_index <= index {
|
||||
let tcmd = &mut assembly[dumped_index];
|
||||
@@ -1014,7 +1047,8 @@ impl ECSImage for ECSExecutionImage {
|
||||
disasm.stream.pos = cmd.addr as usize + 1;
|
||||
let csom = disasm.read_csom()?;
|
||||
let num_args = disasm.stream.read_i32()?;
|
||||
let func_name = WideString::unpack(&mut disasm.stream, false, Encoding::Utf16LE)?.0;
|
||||
let func_name =
|
||||
WideString::unpack(&mut disasm.stream, false, Encoding::Utf16LE, &None)?.0;
|
||||
let mut is_mess = false;
|
||||
if csom == CsomAuto && num_args == 1 && func_name == "Mess" {
|
||||
is_mess = true;
|
||||
@@ -1103,7 +1137,7 @@ impl ECSImage for ECSExecutionImage {
|
||||
new_image.write_u8(CsicLoad.into())?;
|
||||
new_image.write_u8(CsomImmediate.into())?;
|
||||
new_image.write_u8(CsvtString.into())?;
|
||||
WideString(mes).pack(&mut new_image, false, Encoding::Utf8)?;
|
||||
WideString(mes).pack(&mut new_image, false, Encoding::Utf8, &None)?;
|
||||
new_assembly.push(tcmd);
|
||||
let mut tcmd = if tmp_index <= post_index {
|
||||
let data = assembly[tmp_index].clone();
|
||||
@@ -1131,6 +1165,7 @@ impl ECSImage for ECSExecutionImage {
|
||||
&mut new_image,
|
||||
false,
|
||||
Encoding::Utf16LE,
|
||||
&None,
|
||||
)?;
|
||||
new_assembly.push(tcmd);
|
||||
let mut tcmd = if tmp_index <= post_index {
|
||||
@@ -1215,7 +1250,7 @@ impl ECSImage for ECSExecutionImage {
|
||||
new_image.write_u8(CsicLoad.into())?;
|
||||
new_image.write_u8(lcsom.into())?;
|
||||
new_image.write_u8(lcsvt.into())?;
|
||||
WideString(name).pack(&mut new_image, false, Encoding::Utf8)?;
|
||||
WideString(name).pack(&mut new_image, false, Encoding::Utf8, &None)?;
|
||||
dumped_index += 1;
|
||||
while dumped_index <= index {
|
||||
let tcmd = &mut assembly[dumped_index];
|
||||
@@ -1274,7 +1309,7 @@ impl ECSImage for ECSExecutionImage {
|
||||
new_image.write_u8(CsicLoad.into())?;
|
||||
new_image.write_u8(lcsom.into())?;
|
||||
new_image.write_u8(lcsvt.into())?;
|
||||
WideString(message).pack(&mut new_image, false, Encoding::Utf8)?;
|
||||
WideString(message).pack(&mut new_image, false, Encoding::Utf8, &None)?;
|
||||
dumped_index += 1;
|
||||
while dumped_index <= index {
|
||||
let tcmd = &mut assembly[dumped_index];
|
||||
@@ -1339,7 +1374,7 @@ impl ECSImage for ECSExecutionImage {
|
||||
new_image.write_u8(CsicLoad.into())?;
|
||||
new_image.write_u8(lcsom.into())?;
|
||||
new_image.write_u8(lcsvt.into())?;
|
||||
WideString(message).pack(&mut new_image, false, Encoding::Utf8)?;
|
||||
WideString(message).pack(&mut new_image, false, Encoding::Utf8, &None)?;
|
||||
dumped_index += 1;
|
||||
while dumped_index <= index {
|
||||
let tcmd = &mut assembly[dumped_index];
|
||||
@@ -1357,7 +1392,7 @@ impl ECSImage for ECSExecutionImage {
|
||||
} else if is_enter {
|
||||
disasm.stream.pos = cmd.addr as usize + 1;
|
||||
let original_name =
|
||||
WideString::unpack(&mut disasm.stream, false, Encoding::Utf16LE)?.0;
|
||||
WideString::unpack(&mut disasm.stream, false, Encoding::Utf16LE, &None)?.0;
|
||||
let num_args = disasm.stream.read_i32()?;
|
||||
if num_args == 0 {
|
||||
pre_enter_name = original_name.clone();
|
||||
@@ -1426,7 +1461,7 @@ impl ECSImage for ECSExecutionImage {
|
||||
new_image.write_u8(code)?;
|
||||
new_image.write_u8(csom)?;
|
||||
new_image.write_u8(csvt)?;
|
||||
s.pack(&mut new_image, false, Encoding::Utf8)?;
|
||||
s.pack(&mut new_image, false, Encoding::Utf8, &None)?;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//! Ported from CSXTools C# project
|
||||
//! Ported from CSXTool C# project
|
||||
//! See parent module documentation for more details.
|
||||
mod disasm;
|
||||
mod img;
|
||||
|
||||
@@ -129,8 +129,13 @@ impl DerefMut for DWordArray {
|
||||
pub struct WideString(pub String);
|
||||
|
||||
impl StructUnpack for WideString {
|
||||
fn unpack<R: Read + Seek>(reader: &mut R, big: bool, encoding: Encoding) -> Result<Self> {
|
||||
let length = u32::unpack(reader, big, encoding)? as usize;
|
||||
fn unpack<R: Read + Seek>(
|
||||
reader: &mut R,
|
||||
big: bool,
|
||||
encoding: Encoding,
|
||||
info: &Option<Box<dyn std::any::Any>>,
|
||||
) -> Result<Self> {
|
||||
let length = u32::unpack(reader, big, encoding, info)? as usize;
|
||||
let to_read = length * 2;
|
||||
let buf = reader.read_exact_vec(to_read)?;
|
||||
let enc = if big {
|
||||
@@ -144,7 +149,13 @@ impl StructUnpack for WideString {
|
||||
}
|
||||
|
||||
impl StructPack for WideString {
|
||||
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<()> {
|
||||
let enc = if big {
|
||||
Encoding::Utf16BE
|
||||
} else {
|
||||
@@ -152,7 +163,7 @@ impl StructPack for WideString {
|
||||
};
|
||||
let encoded = encode_string(enc, &self.0, false)?;
|
||||
let length = (encoded.len() / 2) as u32;
|
||||
length.pack(writer, big, encoding)?;
|
||||
length.pack(writer, big, encoding, info)?;
|
||||
writer.write_all(&encoded)?;
|
||||
Ok(())
|
||||
}
|
||||
@@ -204,7 +215,7 @@ impl ECSObject {
|
||||
.map_err(|typ| anyhow::anyhow!("Invalid CSVariableType: {}", typ))?;
|
||||
match obj_typ {
|
||||
CSVariableType::CsvtObject => {
|
||||
let class_name = WideString::unpack(reader, false, Encoding::Utf8)?.0;
|
||||
let class_name = WideString::unpack(reader, false, Encoding::Utf8, &None)?.0;
|
||||
return Ok(ECSObject::ClassInfoObject(class_name));
|
||||
}
|
||||
CSVariableType::CsvtReference => {
|
||||
@@ -236,7 +247,7 @@ impl ECSObject {
|
||||
return Ok(ECSObject::Real(val));
|
||||
}
|
||||
CSVariableType::CsvtString => {
|
||||
let s = WideString::unpack(reader, false, Encoding::Utf8)?.0;
|
||||
let s = WideString::unpack(reader, false, Encoding::Utf8, &None)?.0;
|
||||
return Ok(ECSObject::String(s));
|
||||
}
|
||||
_ => {
|
||||
@@ -250,7 +261,7 @@ impl ECSObject {
|
||||
ECSObject::ClassInfoObject(name) => {
|
||||
let obj_type: u8 = CSVariableType::CsvtObject.into();
|
||||
writer.write_i32(obj_type as i32)?;
|
||||
WideString(name.clone()).pack(writer, false, Encoding::Utf8)?;
|
||||
WideString(name.clone()).pack(writer, false, Encoding::Utf8, &None)?;
|
||||
}
|
||||
ECSObject::Reference => {
|
||||
let obj_type: u8 = CSVariableType::CsvtReference.into();
|
||||
@@ -285,7 +296,7 @@ impl ECSObject {
|
||||
ECSObject::String(s) => {
|
||||
let obj_type: u8 = CSVariableType::CsvtString.into();
|
||||
writer.write_i32(obj_type as i32)?;
|
||||
WideString(s.clone()).pack(writer, false, Encoding::Utf8)?;
|
||||
WideString(s.clone()).pack(writer, false, Encoding::Utf8, &None)?;
|
||||
}
|
||||
_ => {
|
||||
return Err(anyhow::anyhow!(
|
||||
@@ -380,7 +391,7 @@ impl DerefMut for ECSExecutionImageAssembly {
|
||||
fn test_exi_header_unpack() {
|
||||
let data = b"\x01\x00\x00\x00";
|
||||
let mut cursor = MemReaderRef::new(data);
|
||||
let header = EXIHeader::unpack(&mut cursor, false, Encoding::Utf8).unwrap();
|
||||
let header = EXIHeader::unpack(&mut cursor, false, Encoding::Utf8, &None).unwrap();
|
||||
assert_eq!(header.version, 1);
|
||||
assert_eq!(header.int_base, 0);
|
||||
}
|
||||
|
||||
144
src/scripts/entis_gls/csx/v2/img.rs
Normal file
144
src/scripts/entis_gls/csx/v2/img.rs
Normal file
@@ -0,0 +1,144 @@
|
||||
use super::super::base::*;
|
||||
use super::types::*;
|
||||
use crate::ext::io::*;
|
||||
use crate::scripts::base::*;
|
||||
use crate::types::*;
|
||||
use crate::utils::struct_pack::*;
|
||||
use anyhow::Result;
|
||||
use std::collections::HashMap;
|
||||
|
||||
const ID_HEADER: u64 = 0x2020726564616568; // header
|
||||
const ID_IMAGE: u64 = 0x2020206567616D69;
|
||||
const ID_IMAGE_GLOBAL: u64 = 0x6C626F6C67676D69;
|
||||
const ID_IMAGE_CONST: u64 = 0x74736E6F63676D69;
|
||||
const ID_IMAGE_SHARED: u64 = 0x6572616873676D69;
|
||||
const ID_CLASS_INFO: u64 = 0x666E697373616C63;
|
||||
const ID_FUNCTION: u64 = 0x6E6F6974636E7566;
|
||||
const ID_INIT_NAKED_FUNC: u64 = 0x636E666E74696E69;
|
||||
const ID_FUNC_INFO: u64 = 0x6F666E69636E7566;
|
||||
const ID_SYMBOL_INFO: u64 = 0x666E696C626D7973;
|
||||
const ID_GLOBAL: u64 = 0x20206C61626F6C67;
|
||||
const ID_DATA: u64 = 0x2020202061746164;
|
||||
const ID_CONST_STRING: u64 = 0x72747374736E6F63;
|
||||
const ID_LINK_INFO: u64 = 0x20666E696B6E696C;
|
||||
const ID_LINK_INFO_EX: u64 = 0x343678656B6E696C;
|
||||
const ID_REF_FUNC: u64 = 0x20636E7566666572;
|
||||
const ID_REF_CODE: u64 = 0x2065646F63666572;
|
||||
const ID_REF_CLASS: u64 = 0x7373616C63666572;
|
||||
const ID_IMPORT_NATIVE_FUNC: u64 = 0x766974616E706D69;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[allow(unused)]
|
||||
pub struct ECSExecutionImage {
|
||||
file_header: FileHeader,
|
||||
section_header: SectionHeader,
|
||||
image: MemReader,
|
||||
image_global: Option<MemReader>,
|
||||
image_const: Option<MemReader>,
|
||||
image_shared: Option<MemReader>,
|
||||
}
|
||||
|
||||
impl ECSExecutionImage {
|
||||
pub fn new(mut reader: MemReaderRef<'_>, _config: &ExtraConfig) -> Result<Self> {
|
||||
let file_header = FileHeader::unpack(&mut reader, false, Encoding::Utf8, &None)?;
|
||||
if file_header.signagure != *b"Entis\x1a\0\0" {
|
||||
return Err(anyhow::anyhow!("Invalid EMC file signature"));
|
||||
}
|
||||
if !file_header.format_desc.starts_with(b"Cotopha Image file") {
|
||||
return Err(anyhow::anyhow!("Invalid EMC file format description"));
|
||||
}
|
||||
let mut section_header = SectionHeader::default();
|
||||
let len = reader.data.len();
|
||||
let mut image = None;
|
||||
let mut image_global = None;
|
||||
let mut image_const = None;
|
||||
let mut image_shared = None;
|
||||
while reader.pos < len {
|
||||
if len - reader.pos < 16 {
|
||||
break;
|
||||
}
|
||||
let id = reader.read_u64()?;
|
||||
if id == 0 {
|
||||
break;
|
||||
}
|
||||
let size = reader.read_u64()?;
|
||||
let pos = reader.pos;
|
||||
match id {
|
||||
ID_HEADER => {
|
||||
let mut mem = StreamRegion::with_size(&mut reader, size)?;
|
||||
section_header = SectionHeader::unpack(&mut mem, false, Encoding::Utf8, &None)?;
|
||||
}
|
||||
ID_IMAGE => {
|
||||
image = Some(MemReader::new(reader.read_exact_vec(size as usize)?));
|
||||
}
|
||||
ID_IMAGE_GLOBAL => {
|
||||
image_global = Some(MemReader::new(reader.read_exact_vec(size as usize)?));
|
||||
}
|
||||
ID_IMAGE_CONST => {
|
||||
image_const = Some(MemReader::new(reader.read_exact_vec(size as usize)?));
|
||||
}
|
||||
ID_IMAGE_SHARED => {
|
||||
image_shared = Some(MemReader::new(reader.read_exact_vec(size as usize)?));
|
||||
}
|
||||
0 => {
|
||||
break;
|
||||
}
|
||||
_ => {
|
||||
return Err(anyhow::anyhow!(
|
||||
"Unknown ECSExecutionImage section ID: 0x{:016X}",
|
||||
id
|
||||
));
|
||||
}
|
||||
}
|
||||
reader.pos = pos + size as usize;
|
||||
}
|
||||
Ok(Self {
|
||||
file_header,
|
||||
section_header,
|
||||
image: image.ok_or_else(|| anyhow::anyhow!("Missing image data"))?,
|
||||
image_global,
|
||||
image_const,
|
||||
image_shared,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl ECSImage for ECSExecutionImage {
|
||||
fn disasm<'a>(&self, _writer: Box<dyn std::io::Write + 'a>) -> Result<()> {
|
||||
Err(anyhow::anyhow!("Disassembly not implemented for CSX v2"))
|
||||
}
|
||||
|
||||
fn export(&self) -> Result<Vec<Message>> {
|
||||
Err(anyhow::anyhow!("Export not implemented for CSX v2"))
|
||||
}
|
||||
|
||||
fn export_multi(&self) -> Result<HashMap<String, Vec<Message>>> {
|
||||
Err(anyhow::anyhow!("Export multi not implemented for CSX v2"))
|
||||
}
|
||||
|
||||
fn export_all(&self) -> Result<Vec<String>> {
|
||||
Err(anyhow::anyhow!("Export all not implemented for CSX v2"))
|
||||
}
|
||||
|
||||
fn import<'a>(
|
||||
&self,
|
||||
_messages: Vec<Message>,
|
||||
_file: Box<dyn WriteSeek + 'a>,
|
||||
_replacement: Option<&'a ReplacementTable>,
|
||||
) -> Result<()> {
|
||||
Err(anyhow::anyhow!("Import not implemented for CSX v2"))
|
||||
}
|
||||
|
||||
fn import_multi<'a>(
|
||||
&self,
|
||||
_messages: HashMap<String, Vec<Message>>,
|
||||
_file: Box<dyn WriteSeek + 'a>,
|
||||
_replacement: Option<&'a ReplacementTable>,
|
||||
) -> Result<()> {
|
||||
Err(anyhow::anyhow!("Import multi not implemented for CSX v2"))
|
||||
}
|
||||
|
||||
fn import_all<'a>(&self, _messages: Vec<String>, _file: Box<dyn WriteSeek + 'a>) -> Result<()> {
|
||||
Err(anyhow::anyhow!("Import all not implemented for CSX v2"))
|
||||
}
|
||||
}
|
||||
6
src/scripts/entis_gls/csx/v2/mod.rs
Normal file
6
src/scripts/entis_gls/csx/v2/mod.rs
Normal file
@@ -0,0 +1,6 @@
|
||||
//! Ported from CSXToolPlus C# project
|
||||
//! See parent module documentation for more details.
|
||||
mod img;
|
||||
mod types;
|
||||
|
||||
pub use img::ECSExecutionImage as ECSExecutionImageV2;
|
||||
448
src/scripts/entis_gls/csx/v2/types.rs
Normal file
448
src/scripts/entis_gls/csx/v2/types.rs
Normal file
@@ -0,0 +1,448 @@
|
||||
use crate::ext::io::*;
|
||||
use crate::types::*;
|
||||
use crate::utils::encoding::*;
|
||||
use crate::utils::struct_pack::*;
|
||||
use anyhow::Result;
|
||||
use int_enum::IntEnum;
|
||||
use msg_tool_macro::{StructPack, StructUnpack};
|
||||
use std::io::{Read, Seek, Write};
|
||||
|
||||
#[repr(u8)]
|
||||
#[derive(Debug, IntEnum, PartialEq, Eq, Clone, Copy)]
|
||||
pub enum CSCompareType {
|
||||
CsctNotEqual,
|
||||
CsctEqual,
|
||||
CsctLessThan,
|
||||
CsctLessEqual,
|
||||
CsctGreaterThan,
|
||||
CsctGreaterEqual,
|
||||
CsctNotEqualPointer,
|
||||
CsctEqualPointer,
|
||||
}
|
||||
|
||||
pub use CSCompareType::*;
|
||||
|
||||
#[repr(u8)]
|
||||
#[derive(Debug, IntEnum, PartialEq, Eq, Clone, Copy)]
|
||||
pub enum CSExtraOperatorType {
|
||||
CsxotArrayDim,
|
||||
CsxotHashContainer,
|
||||
CsxotMoveReference,
|
||||
}
|
||||
|
||||
pub use CSExtraOperatorType::*;
|
||||
|
||||
#[repr(u8)]
|
||||
#[derive(Debug, IntEnum, PartialEq, Eq, Clone, Copy)]
|
||||
pub enum CSExtraUniOperatorType {
|
||||
CsxuotDeselect,
|
||||
CsxuotBoolean,
|
||||
CsxuotSizeOf,
|
||||
CsxuotTypeOf,
|
||||
CsxuotStaticCast,
|
||||
CsxuotDynamicCast,
|
||||
CsxuotDuplicate,
|
||||
CsxuotDelete,
|
||||
CsxuotDeleteArray,
|
||||
CsxuotLoadAddress,
|
||||
CsxuotRefAddress,
|
||||
}
|
||||
|
||||
pub use CSExtraUniOperatorType::*;
|
||||
|
||||
#[repr(u8)]
|
||||
#[derive(Debug, IntEnum, PartialEq, Eq, Clone, Copy)]
|
||||
pub enum CSInstructionCode {
|
||||
CsicNew = 0,
|
||||
CsicFree = 1,
|
||||
CsicLoad = 2,
|
||||
CsicStore = 3,
|
||||
CsicEnter = 4,
|
||||
CsicLeave = 5,
|
||||
CsicJump = 6,
|
||||
CsicCJump = 7,
|
||||
CsicCall = 8,
|
||||
CsicReturn = 9,
|
||||
CsicElement = 10,
|
||||
CsicElementIndirect = 11,
|
||||
CsicOperate = 12,
|
||||
CsicUniOperate = 13,
|
||||
CsicCompare = 14,
|
||||
CsicExOperate = 15,
|
||||
CsicExUniOperate = 16,
|
||||
CsicExCall = 17,
|
||||
CsicExReturn = 18,
|
||||
CsicCallMember = 19,
|
||||
CsicCallNativeMember = 20,
|
||||
CsicSwap = 21,
|
||||
CsicCreateBufferVSize = 23,
|
||||
CsicPointerToObject = 24,
|
||||
CsicReferenceForPointer = 26,
|
||||
CsicCallNativeFunction = 29,
|
||||
// Shell
|
||||
CodeLoadMem = 0x80,
|
||||
CodeLoadMemBaseImm32,
|
||||
CodeLoadMemBaseIndex,
|
||||
CodeLoadMemBaseIndexImm32,
|
||||
CodeStoreMem = 0x84,
|
||||
CodeStoreMemBaseImm32,
|
||||
CodeStoreMemBaseIndex,
|
||||
CodeStoreMemBaseIndexImm32,
|
||||
CodeLoadLocal = 0x88,
|
||||
CodeLoadLocalIndexImm32,
|
||||
CodeStoreLocal = 0x8A,
|
||||
CodeStoreLocalIndexImm32,
|
||||
CodeMoveReg = 0x90,
|
||||
CodeCvtFloat2Int = 0x92,
|
||||
CodeCvtInt2Float = 0x93,
|
||||
CodeSrlImm8 = 0x94,
|
||||
CodeSraImm8,
|
||||
CodeSllImm8,
|
||||
CodeMaskMove,
|
||||
CodeAddImm32 = 0x98,
|
||||
CodeMulImm32,
|
||||
CodeAddSPImm32 = 0x9A,
|
||||
CodeLoadImm64 = 0x9B,
|
||||
CodeNegInt = 0x9C,
|
||||
CodeNotInt,
|
||||
CodeNegFloat,
|
||||
CodeAddReg = 0xA0,
|
||||
CodeSubReg,
|
||||
CodeMulReg,
|
||||
CodeDivReg,
|
||||
CodeModReg,
|
||||
CodeAndReg,
|
||||
CodeOrReg,
|
||||
CodeXorReg,
|
||||
CodeSrlReg,
|
||||
CodeSraReg,
|
||||
CodeSllReg,
|
||||
CodeMoveSx32Reg = 0xAB,
|
||||
CodeMoveSx16Reg,
|
||||
CodeMoveSx8Reg,
|
||||
CodeFAddReg = 0xB0,
|
||||
CodeFSubReg,
|
||||
CodeFMulReg,
|
||||
CodeFDivReg,
|
||||
CodeMul32Reg = 0xB8,
|
||||
CodeIMul32Reg,
|
||||
CodeDiv32Reg,
|
||||
CodeIDiv32Reg,
|
||||
CodeMod32Reg,
|
||||
CodeIMod32Reg,
|
||||
CodeCmpNeReg = 0xC0,
|
||||
CodeCmpEqReg,
|
||||
CodeCmpLtReg,
|
||||
CodeCmpLeReg,
|
||||
CodeCmpGtReg,
|
||||
CodeCmpGeReg,
|
||||
CodeCmpCReg,
|
||||
CodeCmpCZReg,
|
||||
CodeFCmpNeReg = 0xC8,
|
||||
CodeFCmpEqReg,
|
||||
CodeFCmpLtReg,
|
||||
CodeFCmpLeReg,
|
||||
CodeFCmpGtReg,
|
||||
CodeFCmpGeReg,
|
||||
CodeJumpOffset32 = 0xD0,
|
||||
CodeJumpReg = 0xD1,
|
||||
CodeCNJumpOffset32 = 0xD2,
|
||||
CodeCJumpOffset32,
|
||||
CodeCallImm32 = 0xD4,
|
||||
CodeCallReg = 0xD5,
|
||||
CodeSysCallImm32 = 0xD6,
|
||||
CodeSysCallReg = 0xD7,
|
||||
CodeReturn = 0xD8,
|
||||
CodePushReg = 0xDC,
|
||||
CodePopReg,
|
||||
CodePushRegs,
|
||||
CodePopRegs,
|
||||
CodeMemoryHint = 0xE0,
|
||||
CodeFloatExtension,
|
||||
CodeSIMD64Extension2Op,
|
||||
CodeSIMD64Extension3Op,
|
||||
CodeSIMD128Extension2Op,
|
||||
CodeSIMD128Extension3Op,
|
||||
CodeEscape = 0xFD,
|
||||
CodeNoOperation = 0xFE,
|
||||
CodeSystemReserved = 0xFF,
|
||||
}
|
||||
|
||||
pub use CSInstructionCode::*;
|
||||
pub use CodeLoadLocal as CodeLoadLocalImm32;
|
||||
pub use CodeLoadMem as CodeLoadMemBase;
|
||||
pub use CodeStoreLocal as CodeStoreLocalImm32;
|
||||
pub use CodeStoreMem as CodeStoreMemBase;
|
||||
|
||||
#[repr(u8)]
|
||||
#[derive(Debug, IntEnum, PartialEq, Eq, Clone, Copy)]
|
||||
pub enum CSObjectMode {
|
||||
CsomImmediate,
|
||||
CsomStack,
|
||||
CsomThis,
|
||||
CsomGlobal,
|
||||
CsomData,
|
||||
CsomAuto,
|
||||
}
|
||||
|
||||
pub use CSObjectMode::*;
|
||||
|
||||
#[repr(u8)]
|
||||
#[derive(Debug, IntEnum, PartialEq, Eq, Clone, Copy)]
|
||||
pub enum CSOperatorType {
|
||||
CsotNop = 0xFF,
|
||||
CsotAdd = 0,
|
||||
CsotSub,
|
||||
CsotMul,
|
||||
CsotDiv,
|
||||
CsotMod,
|
||||
CsotAnd,
|
||||
CsotOr,
|
||||
CsotXor,
|
||||
CsotLogicalAnd,
|
||||
CsotLogicalOr,
|
||||
CsotShiftRight,
|
||||
CsotShiftLeft,
|
||||
}
|
||||
|
||||
pub use CSOperatorType::*;
|
||||
|
||||
#[repr(u8)]
|
||||
#[derive(Debug, IntEnum, PartialEq, Eq, Clone, Copy)]
|
||||
pub enum CSUnaryOperatorType {
|
||||
CsuotPlus,
|
||||
CsuotNegate,
|
||||
CsuotBitnot,
|
||||
CsuotLogicalNot,
|
||||
}
|
||||
|
||||
pub use CSUnaryOperatorType::*;
|
||||
|
||||
#[repr(u8)]
|
||||
#[derive(Debug, IntEnum, PartialEq, Eq, Clone, Copy)]
|
||||
pub enum CSVariableType {
|
||||
CsvtObject,
|
||||
CsvtReference,
|
||||
CsvtArray,
|
||||
CsvtHash,
|
||||
CsvtInteger,
|
||||
CsvtReal,
|
||||
CsvtString,
|
||||
CsvtInteger64,
|
||||
CsvtPointer,
|
||||
CsvtClassObject,
|
||||
CsvtBoolean,
|
||||
CsvtInt8,
|
||||
CsvtUint8,
|
||||
CsvtInt16,
|
||||
CsvtUint16,
|
||||
CsvtInt32,
|
||||
CsvtUint32,
|
||||
CsvtArrayDimension,
|
||||
CsvtHashContainer,
|
||||
CsvtReal32,
|
||||
CsvtReal64,
|
||||
CsvtPointerReference,
|
||||
CsvtBuffer,
|
||||
CsvtFunction,
|
||||
}
|
||||
|
||||
pub use CSVariableType::*;
|
||||
|
||||
#[derive(Clone, Debug, StructPack, StructUnpack)]
|
||||
pub struct FileHeader {
|
||||
pub signagure: [u8; 8],
|
||||
pub file_id: u32,
|
||||
pub _reserved: u32,
|
||||
pub format_desc: [u8; 48],
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, msg_tool_macro::Default)]
|
||||
pub struct SectionHeader {
|
||||
#[default(3)]
|
||||
pub full_ver: u32,
|
||||
pub header_size: u32,
|
||||
pub version: u32,
|
||||
pub int_base: u32,
|
||||
pub container_flags: u32,
|
||||
pub _reserved: u32,
|
||||
pub stack_size: u32,
|
||||
pub heap_size: u32,
|
||||
pub entry_point: u32,
|
||||
pub static_initialize: u32,
|
||||
pub resume_prepare: u32,
|
||||
}
|
||||
|
||||
impl StructUnpack for SectionHeader {
|
||||
fn unpack<R: Read + Seek>(
|
||||
reader: &mut R,
|
||||
big: bool,
|
||||
encoding: Encoding,
|
||||
info: &Option<Box<dyn std::any::Any>>,
|
||||
) -> Result<Self> {
|
||||
let full_ver = 3;
|
||||
let header_size = reader.stream_length()? as u32;
|
||||
let version = if header_size >= 4 {
|
||||
u32::unpack(reader, big, encoding, info)?
|
||||
} else {
|
||||
0
|
||||
};
|
||||
let int_base = if header_size >= 8 {
|
||||
u32::unpack(reader, big, encoding, info)?
|
||||
} else {
|
||||
0
|
||||
};
|
||||
let container_flags = if header_size >= 12 {
|
||||
u32::unpack(reader, big, encoding, info)?
|
||||
} else {
|
||||
0
|
||||
};
|
||||
let _reserved = if header_size >= 16 {
|
||||
u32::unpack(reader, big, encoding, info)?
|
||||
} else {
|
||||
0
|
||||
};
|
||||
let stack_size = if header_size >= 20 {
|
||||
u32::unpack(reader, big, encoding, info)?
|
||||
} else {
|
||||
0
|
||||
};
|
||||
let heap_size = if header_size >= 24 {
|
||||
u32::unpack(reader, big, encoding, info)?
|
||||
} else {
|
||||
0
|
||||
};
|
||||
let entry_point = if header_size >= 28 {
|
||||
u32::unpack(reader, big, encoding, info)?
|
||||
} else {
|
||||
0
|
||||
};
|
||||
let static_initialize = if header_size >= 32 {
|
||||
u32::unpack(reader, big, encoding, info)?
|
||||
} else {
|
||||
0
|
||||
};
|
||||
let resume_prepare = if header_size >= 36 {
|
||||
u32::unpack(reader, big, encoding, info)?
|
||||
} else {
|
||||
0
|
||||
};
|
||||
Ok(Self {
|
||||
full_ver,
|
||||
header_size,
|
||||
version,
|
||||
int_base,
|
||||
container_flags,
|
||||
_reserved,
|
||||
stack_size,
|
||||
heap_size,
|
||||
entry_point,
|
||||
static_initialize,
|
||||
resume_prepare,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl StructPack for SectionHeader {
|
||||
fn pack<W: Write>(
|
||||
&self,
|
||||
writer: &mut W,
|
||||
big: bool,
|
||||
encoding: Encoding,
|
||||
info: &Option<Box<dyn std::any::Any>>,
|
||||
) -> Result<()> {
|
||||
if self.header_size >= 4 {
|
||||
self.version.pack(writer, big, encoding, info)?;
|
||||
}
|
||||
if self.header_size >= 8 {
|
||||
self.int_base.pack(writer, big, encoding, info)?;
|
||||
}
|
||||
if self.header_size >= 12 {
|
||||
self.container_flags.pack(writer, big, encoding, info)?;
|
||||
}
|
||||
if self.header_size >= 16 {
|
||||
self._reserved.pack(writer, big, encoding, info)?;
|
||||
}
|
||||
if self.header_size >= 20 {
|
||||
self.stack_size.pack(writer, big, encoding, info)?;
|
||||
}
|
||||
if self.header_size >= 24 {
|
||||
self.heap_size.pack(writer, big, encoding, info)?;
|
||||
}
|
||||
if self.header_size >= 28 {
|
||||
self.entry_point.pack(writer, big, encoding, info)?;
|
||||
}
|
||||
if self.header_size >= 32 {
|
||||
self.static_initialize.pack(writer, big, encoding, info)?;
|
||||
}
|
||||
if self.header_size >= 36 {
|
||||
self.resume_prepare.pack(writer, big, encoding, info)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct WideString(pub String);
|
||||
|
||||
impl StructUnpack for WideString {
|
||||
fn unpack<R: Read + Seek>(
|
||||
reader: &mut R,
|
||||
big: bool,
|
||||
encoding: Encoding,
|
||||
info: &Option<Box<dyn std::any::Any>>,
|
||||
) -> Result<Self> {
|
||||
let length = u32::unpack(reader, big, encoding, info)? as usize;
|
||||
let to_read = length * 2;
|
||||
let buf = reader.read_exact_vec(to_read)?;
|
||||
let enc = if big {
|
||||
Encoding::Utf16BE
|
||||
} else {
|
||||
Encoding::Utf16LE
|
||||
};
|
||||
let s = decode_to_string(enc, &buf, true)?;
|
||||
Ok(Self(s))
|
||||
}
|
||||
}
|
||||
|
||||
impl StructPack for WideString {
|
||||
fn pack<W: Write>(
|
||||
&self,
|
||||
writer: &mut W,
|
||||
big: bool,
|
||||
encoding: Encoding,
|
||||
info: &Option<Box<dyn std::any::Any>>,
|
||||
) -> Result<()> {
|
||||
let enc = if big {
|
||||
Encoding::Utf16BE
|
||||
} else {
|
||||
Encoding::Utf16LE
|
||||
};
|
||||
let encoded = encode_string(enc, &self.0, false)?;
|
||||
let length = (encoded.len() / 2) as u32;
|
||||
length.pack(writer, big, encoding, info)?;
|
||||
writer.write_all(&encoded)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, StructPack, StructUnpack)]
|
||||
pub struct BaseClassInfoEntry {
|
||||
pub flags: u32,
|
||||
pub name: WideString,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, StructPack, StructUnpack)]
|
||||
pub struct ECSCastInterface {
|
||||
pub cast_object: i32,
|
||||
pub var_offset: i32,
|
||||
pub var_bounds: i32,
|
||||
pub func_offset: i32,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, StructPack, StructUnpack)]
|
||||
pub struct BaseClassCastInfoEntry {
|
||||
pub name: WideString,
|
||||
pub pci: ECSCastInterface,
|
||||
pub flags: u32,
|
||||
}
|
||||
Reference in New Issue
Block a user