Add more fmt

This commit is contained in:
2025-06-03 18:32:12 +08:00
parent 4a05d9de64
commit cfd78f0c37
4 changed files with 327 additions and 3 deletions

View File

@@ -63,7 +63,8 @@ pub fn struct_unpack_impl_for_num(item: TokenStream) -> TokenStream {
///
/// * `skip_pack` attribute can be used to skip fields from packing.
/// * `fstring = <len>` attribute can be used to specify a fixed string length for String fields.
#[proc_macro_derive(StructPack, attributes(skip_pack, fstring))]
/// * `fvec = <len>` attribute can be used to specify a fixed vector length for Vec<_> fields.
#[proc_macro_derive(StructPack, attributes(skip_pack, fstring, fvec))]
pub fn struct_pack_derive(input: TokenStream) -> TokenStream {
let a = syn::parse_macro_input!(input as PackStruct);
match a {
@@ -73,6 +74,7 @@ pub fn struct_pack_derive(input: TokenStream) -> TokenStream {
let fields = sut.fields.iter().map(|field| {
let mut skipped = false;
let mut fixed_string: Option<usize> = None;
let mut fixed_vec: Option<usize> = None;
for attr in &field.attrs {
let path = attr.path();
if path.is_ident("skip_pack") {
@@ -85,6 +87,14 @@ pub fn struct_pack_derive(input: TokenStream) -> TokenStream {
}
}
}
} else if path.is_ident("fvec") {
if let syn::Meta::NameValue(nv) = &attr.meta {
if let syn::Expr::Lit(lit) = &nv.value {
if let syn::Lit::Int(s) = &lit.lit {
fixed_vec = Some(s.base10_parse().unwrap());
}
}
}
}
}
if skipped {
@@ -117,6 +127,20 @@ pub fn struct_pack_derive(input: TokenStream) -> TokenStream {
}
}
}
if let Some(segment) = type_path.path.segments.first() {
if segment.ident == "Vec" {
if let Some(fixed_vec) = fixed_vec {
return quote::quote! {
if self.#field_name.len() != #fixed_vec {
return Err(anyhow::anyhow!("Vector length was not equal to {}", #fixed_vec));
}
for item in &self.#field_name {
item.pack(writer, big, encoding)?;
}
};
}
}
}
}
quote::quote! {
self.#field_name.pack(writer, big, encoding)?;
@@ -151,6 +175,7 @@ pub fn struct_pack_derive(input: TokenStream) -> TokenStream {
let fields: Vec<_> = variant.fields.iter().enumerate().map(|(idx, field)| {
let mut skipped = false;
let mut fixed_string: Option<usize> = None;
let mut fixed_vec: Option<usize> = None;
for attr in &field.attrs {
let path = attr.path();
if path.is_ident("skip_pack") {
@@ -163,6 +188,14 @@ pub fn struct_pack_derive(input: TokenStream) -> TokenStream {
}
}
}
} else if path.is_ident("fvec") {
if let syn::Meta::NameValue(nv) = &attr.meta {
if let syn::Expr::Lit(lit) = &nv.value {
if let syn::Lit::Int(s) = &lit.lit {
fixed_vec = Some(s.base10_parse().unwrap());
}
}
}
}
}
if skipped {
@@ -196,6 +229,20 @@ pub fn struct_pack_derive(input: TokenStream) -> TokenStream {
}
}
}
if let Some(segment) = type_path.path.segments.first() {
if segment.ident == "Vec" {
if let Some(fixed_vec) = fixed_vec {
return quote::quote! {
if #field_name.len() != #fixed_vec {
return Err(anyhow::anyhow!("Vector length was not equal to {}", #fixed_vec));
}
for item in &#field_name {
item.pack(writer, big, encoding)?;
}
};
}
}
}
}
quote::quote! {
#field_name.pack(writer, big, encoding)?;
@@ -231,7 +278,8 @@ pub fn struct_pack_derive(input: TokenStream) -> TokenStream {
/// * `skip_unpack` attribute can be used to skip fields from unpacking.
/// * `fstring = <len>` attribute can be used to specify a fixed string length for String fields.
/// * `fstring_no_trim` attribute can be used to disable trimming of fixed strings.
#[proc_macro_derive(StructUnpack, attributes(skip_unpack, fstring, fstring_no_trim))]
/// * `fvec = <len>` attribute can be used to specify a fixed vector length for Vec<_> fields.
#[proc_macro_derive(StructUnpack, attributes(skip_unpack, fstring, fstring_no_trim, fvec))]
pub fn struct_unpack_derive(input: TokenStream) -> TokenStream {
let sut = syn::parse_macro_input!(input as syn::ItemStruct);
let name = sut.ident;
@@ -242,6 +290,7 @@ pub fn struct_unpack_derive(input: TokenStream) -> TokenStream {
let mut skipped = false;
let mut fixed_string: Option<usize> = None;
let mut fstring_no_trim = false;
let mut fixed_vec: Option<usize> = None;
for attr in &field.attrs {
let path = attr.path();
if path.is_ident("skip_unpack") {
@@ -256,6 +305,14 @@ pub fn struct_unpack_derive(input: TokenStream) -> TokenStream {
}
} else if path.is_ident("fstring_no_trim") {
fstring_no_trim = true;
} else if path.is_ident("fvec") {
if let syn::Meta::NameValue(nv) = &attr.meta {
if let syn::Expr::Lit(lit) = &nv.value {
if let syn::Lit::Int(s) = &lit.lit {
fixed_vec = Some(s.base10_parse().unwrap());
}
}
}
}
}
let field_name = match &field.ident {
@@ -285,6 +342,15 @@ pub fn struct_unpack_derive(input: TokenStream) -> TokenStream {
}
}
}
if let Some(segment) = type_path.path.segments.first() {
if segment.ident == "Vec" {
if let Some(fixed_vec) = fixed_vec {
return quote::quote! {
let #field_name = reader.read_struct_vec(#fixed_vec, big, encoding)?;
};
}
}
}
}
quote::quote! {
let #field_name = #field_type::unpack(&mut reader, big, encoding)?;

View File

@@ -531,7 +531,6 @@ pub fn export_script(
}
types::OutputScriptType::Custom => {
let enc = get_output_encoding(arg);
println!("f: {}", f);
script.custom_export(f.as_ref(), enc)?;
}
}

View File

@@ -148,6 +148,109 @@ impl EscudeBinList {
ent.data = data_entry;
}
}
} else if filename == "enum_gfx.bin" {
for ent in self.entries.iter_mut() {
let id = ent.id;
if let ListData::Unknown(unk) = &ent.data {
let mut reader = MemReader::new(unk.clone());
let element_size = if id == 0 {
248
} else if id == 1 {
248
} else if id == 2 {
248
} else if id == 3 {
112
} else if id == 4 {
32
} else if id == 9999 {
1
} else {
return Err(anyhow::anyhow!("Unknown enum gfx ID: {}", id));
};
let len = unk.len();
if len % element_size != 0 {
return Err(anyhow::anyhow!(
"Invalid enum gfx length: {} for ID: {}",
len,
id
));
}
let count = len / element_size;
let data_entry = match id {
0 => ListData::Gfx(EnumGfx::Bgs(
reader.read_struct_vec::<BgT>(count, false, encoding)?,
)),
1 => ListData::Gfx(EnumGfx::Evs(
reader.read_struct_vec::<EvT>(count, false, encoding)?,
)),
2 => ListData::Gfx(EnumGfx::Sts(
reader.read_struct_vec::<StT>(count, false, encoding)?,
)),
3 => ListData::Gfx(EnumGfx::Efxs(
reader.read_struct_vec::<EfxT>(count, false, encoding)?,
)),
4 => ListData::Gfx(EnumGfx::Locs(
reader.read_struct_vec::<LocT>(count, false, encoding)?,
)),
9999 => {
// Special case for unknown enum gfx ID
ListData::Unknown(unk.clone())
}
_ => return Err(anyhow::anyhow!("Unknown enum gfx ID: {}", id)),
};
ent.data = data_entry;
}
}
} else if filename == "enum_snd.bin" {
for ent in self.entries.iter_mut() {
let id = ent.id;
if let ListData::Unknown(unk) = &ent.data {
let mut reader = MemReader::new(unk.clone());
let element_size = if id == 0 {
196
} else if id == 1 {
128
} else if id == 2 {
128
} else if id == 3 {
128
} else if id == 9999 {
1
} else {
return Err(anyhow::anyhow!("Unknown enum sound ID: {}", id));
};
let len = unk.len();
if len % element_size != 0 {
return Err(anyhow::anyhow!(
"Invalid enum sound length: {} for ID: {}",
len,
id
));
}
let count = len / element_size;
let data_entry = match id {
0 => ListData::Snd(EnumSnd::Bgm(
reader.read_struct_vec::<BgmT>(count, false, encoding)?,
)),
1 => ListData::Snd(EnumSnd::Amb(
reader.read_struct_vec::<AmbT>(count, false, encoding)?,
)),
2 => ListData::Snd(EnumSnd::Se(
reader.read_struct_vec::<SeT>(count, false, encoding)?,
)),
3 => ListData::Snd(EnumSnd::Sfx(
reader.read_struct_vec::<SfxT>(count, false, encoding)?,
)),
9999 => {
// Special case for unknown enum sound ID
ListData::Unknown(unk.clone())
}
_ => return Err(anyhow::anyhow!("Unknown enum sound ID: {}", id)),
};
ent.data = data_entry;
}
}
}
}
Ok(())
@@ -238,10 +341,151 @@ enum EnumScr {
Scenes(Vec<SceneT>),
}
#[derive(Debug, Serialize, Deserialize, StructPack, StructUnpack)]
struct BgT {
/// Background image name
#[fstring = 32]
name: String,
/// Background image file name
#[fstring = 64]
file: String,
#[fstring = 128]
option: String,
coverd: u32,
color: u32,
id: u32,
loc: u32,
order: i32,
link: u32,
}
#[derive(Debug, Serialize, Deserialize, StructPack, StructUnpack)]
struct EvT {
/// Event image name
#[fstring = 32]
name: String,
/// Event image file name
#[fstring = 64]
file: String,
#[fstring = 128]
option: String,
coverd: u32,
color: u32,
id: u32,
loc: u32,
order: i32,
link: u32,
}
#[derive(Debug, Serialize, Deserialize, StructPack, StructUnpack)]
struct StT {
#[fstring = 32]
name: String,
#[fstring = 64]
file: String,
#[fstring = 128]
option: String,
coverd: u32,
color: u32,
id: u32,
loc: u32,
order: i32,
link: u32,
}
#[derive(Debug, Serialize, Deserialize, StructPack, StructUnpack)]
struct EfxT {
/// Effect image name
#[fstring = 32]
name: String,
/// Effect image file name
#[fstring = 64]
file: String,
spot: i32,
dx: i32,
dy: i32,
r#loop: bool,
#[fvec = 3]
#[serde(skip, default = "exft_padding")]
padding: Vec<u8>,
}
fn exft_padding() -> Vec<u8> {
vec![0; 3]
}
#[derive(Debug, Serialize, Deserialize, StructPack, StructUnpack)]
struct Point {
x: i16,
y: i16,
}
#[derive(Debug, Serialize, Deserialize, StructPack, StructUnpack)]
struct LocT {
#[fvec = 8]
pt: Vec<Point>,
}
#[derive(Debug, Serialize, Deserialize, StructPack)]
#[serde(tag = "type", content = "data")]
enum EnumGfx {
Bgs(Vec<BgT>),
Evs(Vec<EvT>),
Sts(Vec<StT>),
Efxs(Vec<EfxT>),
Locs(Vec<LocT>),
}
#[derive(Debug, Serialize, Deserialize, StructPack, StructUnpack)]
struct BgmT {
#[fstring = 64]
pub name: String,
#[fstring = 64]
pub file: String,
#[fstring = 64]
pub title: String,
pub order: i32,
}
#[derive(Debug, Serialize, Deserialize, StructPack, StructUnpack)]
struct AmbT {
#[fstring = 64]
pub name: String,
#[fstring = 64]
pub file: String,
}
#[derive(Debug, Serialize, Deserialize, StructPack, StructUnpack)]
struct SeT {
#[fstring = 64]
pub name: String,
#[fstring = 64]
pub file: String,
}
#[derive(Debug, Serialize, Deserialize, StructPack, StructUnpack)]
struct SfxT {
#[fstring = 64]
pub name: String,
#[fstring = 64]
pub file: String,
}
#[derive(Debug, Serialize, Deserialize, StructPack)]
#[serde(tag = "type", content = "data")]
enum EnumSnd {
Bgm(Vec<BgmT>),
Amb(Vec<AmbT>),
Se(Vec<SeT>),
Sfx(Vec<SfxT>),
}
#[derive(Debug, Serialize, Deserialize, StructPack)]
#[serde(tag = "type", content = "data")]
enum ListData {
Scr(EnumScr),
Gfx(EnumGfx),
Snd(EnumSnd),
Unknown(Vec<u8>),
}

View File

@@ -32,3 +32,18 @@ struct_unpack_impl_for_num!(i64);
struct_unpack_impl_for_num!(i128);
struct_unpack_impl_for_num!(f32);
struct_unpack_impl_for_num!(f64);
impl StructUnpack for bool {
fn unpack<R: Read + Seek>(mut reader: R, _big: bool, _encoding: Encoding) -> Result<Self> {
let mut buf = [0u8; 1];
reader.read_exact(&mut buf)?;
Ok(buf[0] != 0)
}
}
impl StructPack for bool {
fn pack<W: Write>(&self, writer: &mut W, _big: bool, _encoding: Encoding) -> Result<()> {
writer.write_all(&[if *self { 1 } else { 0 }])?;
Ok(())
}
}