use crate::{parse_ptr64, parse_string_opt_ptr64, parse_string_ptr64};
use binrw::BinRead;
use xc3_write::{
Xc3Write, Xc3WriteOffsets,
strings::{StringSectionUniqueSorted, WriteOptions},
};
use super::{BcList, BcOffset, StringOffset};
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
#[br(magic(b"ASMB"))]
#[xc3(magic(b"ASMB"))]
pub struct Asmb {
#[br(parse_with = parse_ptr64)]
#[xc3(offset(u64))]
pub inner: AsmbInner,
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
pub enum AsmbInner {
V1(AsmbInnerV1),
V2(AsmbInnerV2),
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, PartialEq, Clone)]
pub struct AsmbInnerV1 {
pub unk1: u32,
pub unk2: i32,
pub folders: BcList<StringOffset>,
pub unk4: BcList<BcOffset<StateV1>>,
pub unk5: BcList<VarParamV1>,
pub unk6: BcList<AnimationV1>,
#[br(parse_with = parse_string_opt_ptr64)]
#[xc3(offset(u64))]
pub skeleton_file_name: Option<String>,
pub unk8: BcList<KeyValueV1>,
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
pub struct StateV1 {
pub unk1: u32,
pub unk2: i32,
#[br(parse_with = parse_string_ptr64)]
#[xc3(offset(u64))]
pub name: String,
pub unk3: [i32; 4],
pub children: BcList<BcOffset<StateTransitionV1>>,
pub unk9: u64,
pub unk10: BcList<StateKeyValueV1>,
pub unk11: BcList<StateKeyValueV1>,
pub unk12: BcList<u64>,
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
pub struct AnimationV1 {
#[br(parse_with = parse_string_ptr64)]
#[xc3(offset(u64))]
pub file_name: String,
pub unk1: BcList<AnimationUnk1V1>,
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
pub struct VarParamV1 {
pub unk1: u32,
pub unk2: i32,
#[br(parse_with = parse_string_ptr64)]
#[xc3(offset(u64))]
pub name: String,
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
pub struct AnimationUnk1V1 {
pub unk1: u16,
pub unk2: u16,
pub unk3: i32,
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
pub struct StateTransitionV1 {
#[br(parse_with = parse_string_ptr64)]
#[xc3(offset(u64))]
pub name: String,
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
pub struct KeyValueV1 {
#[br(parse_with = parse_string_ptr64)]
#[xc3(offset(u64))]
pub key: String,
#[br(parse_with = parse_string_ptr64)]
#[xc3(offset(u64))]
pub value: String,
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
pub struct StateKeyValueV1 {
#[br(parse_with = parse_string_ptr64)]
#[xc3(offset(u64))]
pub key: String,
pub unk1: u32,
pub unk2: i32,
#[br(parse_with = parse_string_ptr64)]
#[xc3(offset(u64))]
pub value: String,
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
pub struct AsmbInnerV2 {
pub folders: BcList<StringOffset>,
pub unk2: BcList<FsmGroupV2>,
pub unk3: u64, pub unk4: BcList<u8>, }
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
pub struct FsmGroupV2 {
pub unk1: BcList<BcOffset<StateV2>>,
pub unk2: BcList<BcOffset<StateTransitionV2>>,
#[br(parse_with = parse_string_ptr64)]
#[xc3(offset(u64))]
pub unk3: String,
#[br(parse_with = parse_string_ptr64)]
#[xc3(offset(u64))]
pub unk4: String,
#[br(parse_with = parse_string_opt_ptr64)]
#[xc3(offset(u64))]
pub unk5: Option<String>,
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
pub struct StateV2 {
#[br(parse_with = parse_string_ptr64)]
#[xc3(offset(u64))]
pub name: String,
pub name_hash: u32,
pub unk3: u32,
pub unk4: u32,
pub unk5: u32,
pub unk6: u32,
pub unk7: u32,
pub children: BcList<BcOffset<StateTransitionV2>>,
pub unk9: BcList<u8>,
pub unk10: BcList<u8>,
pub unk11: BcList<u8>,
pub unk12: BcList<u8>,
pub unk13: BcList<u8>,
#[br(parse_with = parse_string_ptr64)]
#[xc3(offset(u64))]
pub unk14: String,
pub unk15: [f32; 8],
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
pub struct StateTransitionV2 {
#[br(parse_with = parse_string_ptr64)]
#[xc3(offset(u64))]
pub name1: String,
#[br(parse_with = parse_string_ptr64)]
#[xc3(offset(u64))]
pub name2: String,
pub name2_hash: u32,
pub unk4: [f32; 4],
pub unk5: i32,
pub unk6: [f32; 2],
pub unk7: u32,
pub unk8: u32,
pub unk9: [i16; 8],
pub unk10: f32,
pub unk11: u32,
pub unk12: u32,
pub unk13: i32,
}
impl Xc3WriteOffsets for AsmbInnerV1Offsets<'_> {
type Args = ();
fn write_offsets<W: std::io::prelude::Write + std::io::prelude::Seek>(
&self,
writer: &mut W,
base_offset: u64,
data_ptr: &mut u64,
endian: xc3_write::Endian,
_args: Self::Args,
) -> xc3_write::Xc3Result<()> {
let mut string_section = StringSectionUniqueSorted::default();
let folders = self
.folders
.0
.write(writer, base_offset, data_ptr, endian)?;
for f in folders.0 {
string_section.insert_offset64(&f.name);
}
let unk5 = self.unk5.0.write(writer, base_offset, data_ptr, endian)?;
for u in unk5.0 {
string_section.insert_offset64(&u.name);
}
let unk6 = self.unk6.0.write(writer, base_offset, data_ptr, endian)?;
for u in unk6.0 {
string_section.insert_offset64(&u.file_name);
}
let unk4 = self.unk4.0.write(writer, base_offset, data_ptr, endian)?;
for u in unk4.0 {
let u = u.value.write(writer, base_offset, data_ptr, endian)?;
string_section.insert_offset64(&u.name);
let children = u.children.0.write(writer, base_offset, data_ptr, endian)?;
for c in children.0 {
let c = c.value.write(writer, base_offset, data_ptr, endian)?;
string_section.insert_offset64(&c.name);
}
}
let unk8 = self.unk8.0.write(writer, base_offset, data_ptr, endian)?;
for u in unk8.0 {
string_section.insert_offset64(&u.key);
string_section.insert_offset64(&u.value);
}
string_section.write(
writer,
data_ptr,
&WriteOptions {
start_alignment: 8,
start_padding_byte: 0xff,
string_alignment: 1,
string_padding_byte: 0,
},
endian,
)?;
Ok(())
}
}