use crate::{
StringOffset32,
msrd::Streaming,
parse_count32_offset32, parse_offset32_count32, parse_opt_ptr32, parse_ptr32,
parse_string_opt_ptr32, parse_string_ptr32,
spch::Spch,
vertex::{DataType, VertexData},
xc3_write_binwrite_impl,
};
use bilge::prelude::*;
use binrw::{BinRead, BinWrite, args, binread};
use legacy2::MxmdV40;
use xc3_write::{Xc3Write, Xc3WriteOffsets};
pub mod legacy;
pub mod legacy2;
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
#[br(magic(b"DMXM"))]
#[xc3(magic(b"DMXM"))]
pub struct Mxmd {
pub version: u32,
#[br(args_raw(version))]
pub inner: MxmdInner,
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
#[br(import_raw(version: u32))]
pub enum MxmdInner {
#[br(pre_assert(version == 10040))]
V40(MxmdV40),
#[br(pre_assert(version == 10111))]
V111(MxmdV111),
#[br(pre_assert(version == 10112))]
V112(MxmdV112),
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
pub struct MxmdV111 {
#[br(parse_with = parse_ptr32)]
#[xc3(offset(u32))]
pub models: ModelsV111,
#[br(parse_with = parse_ptr32)]
#[xc3(offset(u32))]
pub materials: Materials,
#[br(parse_with = parse_opt_ptr32)]
#[xc3(offset(u32))]
pub unk1: Option<Unk1>,
#[br(parse_with = parse_opt_ptr32)]
#[xc3(offset(u32))]
pub vertex_data: Option<VertexData>,
#[br(parse_with = parse_opt_ptr32)]
#[xc3(offset(u32))]
pub spch: Option<Spch>,
#[br(parse_with = parse_opt_ptr32)]
#[xc3(offset(u32))]
pub packed_textures: Option<PackedTextures>,
pub unk5: u32,
#[br(parse_with = parse_opt_ptr32)]
#[xc3(offset(u32), align(4))]
pub streaming: Option<Streaming>,
pub unk6: u32,
pub unk7: u32,
#[br(parse_with = parse_opt_ptr32)]
#[xc3(offset(u32), align(16))]
pub unk8: Option<Unk8>,
pub unk: [u32; 6],
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, PartialEq, Clone)]
pub struct MxmdV112 {
#[br(parse_with = parse_ptr32)]
#[xc3(offset(u32), align(16))]
pub models: ModelsV112,
#[br(parse_with = parse_ptr32)]
#[xc3(offset(u32), align(16))]
pub materials: Materials,
#[br(parse_with = parse_opt_ptr32)]
#[xc3(offset(u32), align(16))]
pub unk1: Option<Unk1>,
#[br(parse_with = parse_opt_ptr32)]
#[xc3(offset(u32))]
pub vertex_data: Option<VertexData>,
#[br(parse_with = parse_opt_ptr32)]
#[xc3(offset(u32))]
pub spch: Option<Spch>,
#[br(parse_with = parse_opt_ptr32)]
#[xc3(offset(u32))]
pub packed_textures: Option<PackedTextures>,
pub unk5: u32,
#[br(parse_with = parse_opt_ptr32)]
#[xc3(offset(u32), align(4))]
pub streaming: Option<Streaming>,
pub unk6: u32,
pub unk7: u32,
#[br(parse_with = parse_opt_ptr32)]
#[xc3(offset(u32), align(16))]
pub unk8: Option<Unk8>,
pub unk: [u32; 6],
}
#[binread]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, Xc3Write, PartialEq, Clone)]
#[br(stream = r)]
#[xc3(base_offset)]
pub struct Materials {
#[br(temp, try_calc = r.stream_position())]
base_offset: u64,
#[br(temp, restore_position)]
material_offset: u32,
#[br(parse_with = parse_offset32_count32, args { offset: base_offset, inner: base_offset })]
#[xc3(offset_count(u32, u32), align(4))]
pub materials: Vec<Material>,
pub unk1: u32,
pub unk2: u32,
#[br(parse_with = parse_offset32_count32, offset = base_offset)]
#[xc3(offset_count(u32, u32), align(16))]
pub work_values: Vec<f32>,
#[br(parse_with = parse_offset32_count32, offset = base_offset)]
#[xc3(offset_count(u32, u32))]
pub shader_vars: Vec<(u16, u16)>,
#[br(parse_with = parse_opt_ptr32)]
#[br(args { offset: base_offset, inner: base_offset })]
#[xc3(offset(u32))]
pub callbacks: Option<MaterialCallbacks>,
pub unk4: u32,
#[br(parse_with = parse_offset32_count32)]
#[br(args { offset: base_offset, inner: base_offset })]
#[xc3(offset_count(u32, u32))]
pub techniques: Vec<Technique>,
pub unks1: u32,
#[br(parse_with = parse_opt_ptr32)]
#[br(args { offset: base_offset, inner: base_offset })]
#[xc3(offset(u32))]
pub unk6: Option<MaterialUnk6>,
#[br(parse_with = parse_count32_offset32, offset = base_offset)]
#[xc3(count_offset(u32, u32))]
pub alpha_test_textures: Vec<AlphaTestTexture>,
pub unks3: [u32; 3],
#[br(parse_with = parse_opt_ptr32)]
#[br(args { offset: base_offset, inner: base_offset })]
#[xc3(offset(u32))]
pub material_unk2: Option<MaterialUnk2>,
#[br(parse_with = parse_opt_ptr32)]
#[br(args { offset: base_offset, inner: args! { base_offset, count: materials.len() } })]
#[xc3(offset(u32))]
pub fur_shells: Option<FurShells>,
pub unks3_1: [u32; 2],
#[br(parse_with = parse_opt_ptr32, offset = base_offset)]
#[xc3(offset(u32))]
pub samplers: Option<Samplers>,
pub unks4: [u32; 3],
#[br(if(material_offset >= 112))]
#[br(args_raw(base_offset))]
pub unk5: Option<MaterialUnk5>,
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
pub struct AlphaTestTexture {
pub texture_index: u16,
pub sampler_index: u16,
pub unk2: u16, pub unk3: u16, }
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, PartialEq, Clone)]
#[br(import_raw(base_offset: u64))]
pub struct Technique {
#[br(parse_with = parse_offset32_count32, offset = base_offset)]
#[xc3(offset_count(u32, u32))]
pub attributes: Vec<VertexAttribute>,
pub unk3: u32, pub unk4: u32,
#[br(parse_with = parse_offset32_count32, offset = base_offset)]
#[xc3(offset_count(u32, u32))]
pub parameters: Vec<MaterialParameter>,
#[br(parse_with = parse_offset32_count32, offset = base_offset)]
#[xc3(offset_count(u32, u32))]
pub textures: Vec<u16>,
#[br(parse_with = parse_offset32_count32, offset = base_offset)]
#[xc3(offset_count(u32, u32))]
pub uniform_blocks: Vec<UniformBlock>,
pub material_texture_count: u32,
pub unk12: u16, pub unk13: u16,
pub unk14: u32,
#[br(parse_with = parse_offset32_count32, offset = base_offset)]
#[xc3(offset_count(u32, u32))]
pub unk15: Vec<[u32; 5]>,
pub padding: [u32; 2],
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
pub struct UniformBlock {
pub unk1: u16,
pub unk2: u8,
pub unk3: u8,
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
pub struct VertexAttribute {
pub data_type: DataType,
pub relative_offset: u16,
pub buffer_index: u16,
pub unk4: u16, }
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
pub struct MaterialParameter {
pub param_type: ParamType,
pub work_value_index: u16, pub unk: u16,
pub count: u16, }
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, BinWrite, Clone, Copy, PartialEq, Eq, Hash)]
#[brw(repr(u16))]
pub enum ParamType {
DpRat = 0,
TexMatrix = 1,
WorkFloat4 = 2,
WorkColor = 3,
ProjectionTexMatrix = 4,
AlphaInfo = 5,
MaterialColor = 6,
Unk7 = 7,
ToonHeadMatrix = 10,
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, PartialEq, Clone)]
#[br(import_raw(base_offset: u64))]
pub struct MaterialCallbacks {
#[br(parse_with = parse_offset32_count32, offset = base_offset)]
#[xc3(offset_count(u32, u32))]
pub work_callbacks: Vec<WorkCallback>,
#[br(parse_with = parse_offset32_count32, offset = base_offset)]
#[xc3(offset_count(u32, u32))]
pub material_indices: Vec<u16>,
#[br(parse_with = parse_offset32_count32, offset = base_offset)]
#[xc3(offset_count(u32, u32))]
pub unk1: Vec<[u32; 2]>,
pub unk: [u32; 6],
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
pub struct WorkCallback {
pub unk1: u16,
pub unk2: u16,
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
#[br(import_raw(base_offset: u64))]
pub struct MaterialUnk2 {
#[br(parse_with = parse_count32_offset32, offset = base_offset)]
#[xc3(count_offset(u32, u32))]
pub unk1: Vec<[u32; 3]>,
pub unk: [u32; 4],
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, PartialEq, Clone)]
#[br(import { base_offset: u64, count: usize })]
pub struct FurShells {
#[br(parse_with = parse_ptr32)]
#[br(args { offset: base_offset, inner: args! { count }})]
#[xc3(offset(u32))]
pub material_param_indices: Vec<u16>,
#[br(parse_with = parse_offset32_count32, offset = base_offset)]
#[xc3(offset_count(u32, u32))]
pub params: Vec<FurShellParams>,
pub unk: [u32; 4],
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
pub struct FurShellParams {
pub instance_count: u32,
pub view_distance: f32,
pub shell_width: f32,
pub y_offset: f32,
pub alpha: f32,
}
#[binread]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
#[br(stream = r)]
#[xc3(base_offset)]
pub struct Samplers {
#[br(temp, try_calc = r.stream_position())]
base_offset: u64,
#[br(parse_with = parse_count32_offset32, offset = base_offset)]
#[xc3(count_offset(u32, u32))]
pub samplers: Vec<Sampler>,
pub unk: [u32; 2],
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
pub struct Sampler {
pub flags: SamplerFlags,
pub unk2: u16,
pub unk3: f32,
}
#[bitsize(16)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(DebugBits, FromBits, BinRead, BinWrite, PartialEq, Clone, Copy)]
#[br(map = u16::into)]
#[bw(map = |&x| u16::from(x))]
pub struct SamplerFlags {
pub repeat_u: bool,
pub repeat_v: bool,
pub mirror_u: bool,
pub mirror_v: bool,
pub nearest: bool,
pub force_clamp: bool,
pub disable_mipmap_filter: bool,
pub unk1: bool,
pub unk3: bool,
pub unk: u7,
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
#[br(import_raw(base_offset: u64))]
pub struct Material {
#[br(parse_with = parse_string_ptr32, offset = base_offset)]
#[xc3(offset(u32))]
pub name: String,
pub flags: MaterialFlags,
pub render_flags: MaterialRenderFlags,
pub color: [f32; 4],
pub alpha_test_ref: f32,
#[br(parse_with = parse_offset32_count32, offset = base_offset)]
#[xc3(offset_count(u32, u32))]
pub textures: Vec<Texture>,
pub state_flags: StateFlags,
pub m_unks1_1: u32,
pub m_unks1_2: u32,
pub m_unks1_3: u32,
pub m_unks1_4: u32,
pub work_value_start_index: u32,
pub shader_var_start_index: u32,
pub shader_var_count: u32,
#[br(parse_with = parse_offset32_count32, offset = base_offset)]
#[xc3(offset_count(u32, u32))]
pub techniques: Vec<MaterialTechnique>,
pub unk5: u32,
pub callback_start_index: u16,
pub callback_count: u16,
pub m_unks2: [u16; 3],
pub alpha_test_texture_index: u16,
pub m_unk3: u16,
pub gbuffer_flags: u16,
pub m_unk4: [u16; 6],
}
#[bitsize(32)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(DebugBits, FromBits, BinRead, BinWrite, PartialEq, Clone, Copy)]
#[br(map = u32::into)]
#[bw(map = |&x| u32::from(x))]
pub struct MaterialFlags {
pub unk1: bool,
pub unk2: bool,
pub alpha_mask: bool,
pub separate_mask: bool,
pub unk5: bool,
pub unk6: bool,
pub unk7: bool,
pub unk8: bool,
pub unk9: bool,
pub fur: bool,
pub unk11: u17,
pub fur_shells: bool,
pub unk: u4,
}
#[bitsize(32)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(DebugBits, FromBits, BinRead, BinWrite, PartialEq, Clone, Copy)]
#[br(map = u32::into)]
#[bw(map = |&x| u32::from(x))]
pub struct MaterialRenderFlags {
pub unk1: bool,
pub unk2: bool,
pub unk3: bool,
pub unk4: bool,
pub unk5: bool,
pub unk6: bool,
pub speff_zpre: bool, pub unk8: bool,
pub unk9: bool,
pub unk10: bool, pub unk11: bool,
pub specular: bool, pub unk13: bool, pub unk14: bool, pub unk15: bool, pub unk16: bool, pub unk17: bool,
pub unk18: bool,
pub unk19: bool,
pub unk20: bool,
pub speff_ope: bool,
pub unk22: bool,
pub unk23: bool,
pub unk24: bool,
pub unk25: bool,
pub unk26: bool,
pub unk: u6,
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, BinWrite, Clone, Copy, PartialEq, Eq, Hash)]
pub struct StateFlags {
pub depth_write_mode: u8, pub blend_mode: BlendMode,
pub cull_mode: CullMode,
pub unk4: u8, pub stencil_value: StencilValue,
pub stencil_mode: StencilMode,
pub depth_func: DepthFunc,
pub color_write_mode: ColorWriteMode,
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, BinWrite, Clone, Copy, PartialEq, Eq, Hash)]
#[brw(repr(u8))]
pub enum ColorWriteMode {
Unk0 = 0, Unk1 = 1, Unk2 = 2, Unk3 = 3, Unk5 = 5, Unk6 = 6, Unk9 = 9, Unk10 = 10, Unk11 = 11, Unk12 = 12, }
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, BinWrite, Clone, Copy, PartialEq, Eq, Hash)]
#[brw(repr(u8))]
pub enum BlendMode {
Disabled = 0,
Blend = 1,
Unk2 = 2,
Multiply = 3,
MultiplyInverted = 4,
Add = 5,
Disabled2 = 6,
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, BinWrite, Clone, Copy, PartialEq, Eq, Hash)]
#[brw(repr(u8))]
pub enum StencilValue {
Unk0 = 0,
Unk1 = 1,
Unk4 = 4,
Unk5 = 5,
Unk8 = 8,
Unk9 = 9,
Unk12 = 12,
Unk16 = 16,
Unk20 = 20,
Unk33 = 33,
Unk37 = 37,
Unk41 = 41,
Unk49 = 49,
Unk97 = 97,
Unk105 = 105,
Unk128 = 128, }
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, BinWrite, Clone, Copy, PartialEq, Eq, Hash)]
#[brw(repr(u8))]
pub enum StencilMode {
Unk0 = 0, Unk1 = 1, Unk2 = 2, Unk6 = 6, Unk7 = 7, Unk8 = 8, Unk9 = 9, Unk12 = 12, Unk13 = 13, }
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, BinWrite, Clone, Copy, PartialEq, Eq, Hash)]
#[brw(repr(u8))]
pub enum DepthFunc {
Disabled = 0,
LessEqual = 1,
Equal = 3,
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, BinWrite, Clone, Copy, PartialEq, Eq, Hash)]
#[brw(repr(u8))]
pub enum CullMode {
Back = 0,
Front = 1,
Disabled = 2,
Unk3 = 3, }
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
pub struct MaterialTechnique {
pub technique_index: u32,
pub pass_type: RenderPassType,
pub material_buffer_index: u16,
pub flags: u32, }
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, BinWrite, PartialEq, Eq, Clone, Copy, Hash)]
#[brw(repr(u16))]
pub enum RenderPassType {
Unk0 = 0, Unk1 = 1, Unk6 = 6, Unk7 = 7, Unk9 = 9, }
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
pub struct Texture {
pub texture_index: u16,
pub sampler_index: u16,
pub sampler_index2: u16,
pub unk3: u16, }
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
#[br(import_raw(base_offset: u64))]
pub struct MaterialUnk5 {
#[br(parse_with = parse_opt_ptr32, offset = base_offset)]
#[xc3(offset(u32))]
pub unk1: Option<MaterialUnk5Inner>,
}
#[binread]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
#[br(stream = r)]
#[xc3(base_offset)]
pub struct MaterialUnk5Inner {
#[br(temp, try_calc = r.stream_position())]
base_offset: u64,
pub unk1: u32,
#[br(parse_with = parse_count32_offset32, offset = base_offset)]
#[xc3(count_offset(u32, u32))]
pub unk2: Vec<[f32; 6]>,
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
#[br(import_raw(base_offset: u64))]
pub struct MaterialUnk6 {
#[br(parse_with = parse_count32_offset32)]
#[br(args { offset: base_offset, inner: base_offset })]
#[xc3(count_offset(u32, u32))]
pub items: Vec<MaterialUnk6Item>,
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
#[br(import_raw(base_offset: u64))]
pub struct MaterialUnk6Item {
pub unk1: u32,
pub material_index: u32,
pub unk3: u32,
#[br(parse_with = parse_count32_offset32)]
#[br(args { offset: base_offset, inner: base_offset })]
#[xc3(count_offset(u32, u32))]
pub unk4: Vec<MaterialUnk6ItemUnk4>,
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
#[br(import_raw(base_offset: u64))]
pub struct MaterialUnk6ItemUnk4 {
pub unk1: u32,
#[br(parse_with = parse_count32_offset32, offset = base_offset)]
#[xc3(count_offset(u32, u32))]
pub unk2: Vec<[f32; 3]>,
}
#[binread]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, Xc3Write, PartialEq, Clone)]
#[br(stream = r)]
#[xc3(base_offset)]
pub struct ModelsV112 {
#[br(temp, try_calc = r.stream_position())]
base_offset: u64,
pub models_flags: ModelsFlags,
pub max_xyz: [f32; 3],
pub min_xyz: [f32; 3],
#[br(temp, restore_position)]
models_offset: u32,
#[br(parse_with = parse_offset32_count32, args { offset: base_offset, inner: base_offset })]
#[xc3(offset_count(u32, u32))]
pub models: Vec<ModelV112>,
pub unk2: u32,
#[br(parse_with = parse_opt_ptr32, offset = base_offset)]
#[xc3(offset(u32))]
pub skinning: Option<Skinning>,
#[br(parse_with = parse_opt_ptr32, offset = base_offset)]
#[xc3(offset(u32))]
pub model_unk11: Option<ModelUnk11>,
pub unks3_1: [u32; 13],
#[br(parse_with = parse_offset32_count32, args { offset: base_offset, inner: base_offset })]
#[xc3(offset_count(u32, u32), align(16))]
pub ext_meshes: Vec<ExtMesh>,
pub unks3_2: [u32; 2],
#[br(parse_with = parse_opt_ptr32)]
#[br(args { offset: base_offset, inner: base_offset })]
#[xc3(offset(u32))]
pub model_unk8: Option<ModelUnk8>,
pub unk3_3: u32,
#[br(parse_with = parse_opt_ptr32, offset = base_offset)]
#[xc3(offset(u32))]
pub model_unk7: Option<ModelUnk7>,
#[br(parse_with = parse_opt_ptr32, offset = base_offset)]
#[xc3(offset(u32), align(16))]
pub morph_controllers: Option<MorphControllers>,
#[br(parse_with = parse_opt_ptr32, offset = base_offset)]
#[xc3(offset(u32), align(16))]
pub model_unk1: Option<ModelUnk1>,
#[br(parse_with = parse_opt_ptr32, offset = base_offset)]
#[xc3(offset(u32))]
pub model_unk3: Option<ModelUnk3>,
#[br(parse_with = parse_opt_ptr32, offset = base_offset)]
#[xc3(offset(u32), align(8))]
pub lod_data: Option<LodData>,
#[br(parse_with = parse_opt_ptr32, offset = base_offset)]
#[xc3(offset(u32), align(4))]
pub alpha_table: Option<AlphaTable>,
pub unk_field2: u32,
#[br(parse_with = parse_opt_ptr32)]
#[br(args { offset: base_offset, inner: base_offset})]
#[xc3(offset(u32))]
pub model_unk9: Option<ModelUnk9>,
#[br(parse_with = parse_opt_ptr32, offset = base_offset)]
#[xc3(offset(u32))]
pub model_unk12: Option<ModelUnk12>,
#[br(args { size: models_offset, base_offset})]
pub extra: ModelsExtraData,
}
#[binread]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
#[br(stream = r)]
#[xc3(base_offset)]
pub struct ModelsV111 {
#[br(temp, try_calc = r.stream_position())]
base_offset: u64,
pub max_xyz: [f32; 3],
pub min_xyz: [f32; 3],
#[br(parse_with = parse_offset32_count32, args { offset: base_offset, inner: base_offset })]
#[xc3(offset_count(u32, u32))]
pub models: Vec<ModelV111>,
pub unk2: u32,
pub model_unk16: u32,
pub model_unk11: u32,
#[br(parse_with = parse_opt_ptr32, offset = base_offset)]
#[xc3(offset(u32))]
pub skinning: Option<Skinning>,
pub unks3_1: [u32; 12],
pub ext_meshes: [u32; 2],
pub unks3_2: [u32; 2],
pub model_unk8: u32,
pub unk3_3: u32,
#[br(parse_with = parse_opt_ptr32, offset = base_offset)]
#[xc3(offset(u32))]
pub model_unk7: Option<ModelUnk7>,
pub morph_controllers: u32,
pub model_unk1: u32,
pub model_unk12: u32,
pub lod_data: u32,
pub alpha_table: u32,
pub unk_field2: u32,
pub model_unk9: u32,
#[br(parse_with = parse_opt_ptr32, offset = base_offset)]
#[xc3(offset(u32))]
pub model_unk3: Option<ModelUnk3>,
pub model_unk13: u32,
pub model_unk14: u32,
pub model_unk15: u32,
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
#[br(import { size: u32, base_offset: u64 })]
pub enum ModelsExtraData {
#[br(pre_assert(size == 160))]
Unk1,
#[br(pre_assert(size == 164))]
Unk2(#[br(args_raw(base_offset))] ModelsExtraDataUnk2),
#[br(pre_assert(size == 168))]
Unk3(#[br(args_raw(base_offset))] ModelsExtraDataUnk3),
#[br(pre_assert(size == 200))]
Unk4(#[br(args_raw(base_offset))] ModelsExtraDataUnk4),
#[br(pre_assert(size == 204))]
Unk5(#[br(args_raw(base_offset))] ModelsExtraDataUnk5),
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
#[br(import_raw(base_offset: u64))]
pub struct ModelsExtraDataUnk2 {
#[br(parse_with = parse_opt_ptr32)]
#[br(args { offset: base_offset, inner: base_offset })]
#[xc3(offset(u32))]
pub model_unk10: Option<ModelUnk10>,
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
#[br(import_raw(base_offset: u64))]
pub struct ModelsExtraDataUnk3 {
#[br(parse_with = parse_opt_ptr32)]
#[br(args { offset: base_offset, inner: base_offset })]
#[xc3(offset(u32))]
pub model_unk10: Option<ModelUnk10>,
#[br(parse_with = parse_opt_ptr32, offset = base_offset)]
#[xc3(offset(u32))]
pub model_unk5: Option<ModelUnk5>,
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
#[br(import_raw(base_offset: u64))]
pub struct ModelsExtraDataUnk4 {
#[br(parse_with = parse_opt_ptr32)]
#[br(args { offset: base_offset, inner: base_offset })]
#[xc3(offset(u32))]
pub model_unk10: Option<ModelUnk10>,
#[br(parse_with = parse_opt_ptr32, offset = base_offset)]
#[xc3(offset(u32))]
pub model_unk5: Option<ModelUnk5>,
#[br(parse_with = parse_opt_ptr32, offset = base_offset)]
#[xc3(offset(u32))]
pub model_unk6: Option<ModelUnk6>,
pub unk: Option<[u32; 7]>,
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
#[br(import_raw(base_offset: u64))]
pub struct ModelsExtraDataUnk5 {
#[br(parse_with = parse_opt_ptr32)]
#[br(args { offset: base_offset, inner: base_offset })]
#[xc3(offset(u32))]
pub model_unk10: Option<ModelUnk10>,
#[br(parse_with = parse_opt_ptr32, offset = base_offset)]
#[xc3(offset(u32))]
pub model_unk5: Option<ModelUnk5>,
#[br(parse_with = parse_opt_ptr32, offset = base_offset)]
#[xc3(offset(u32))]
pub model_unk6: Option<ModelUnk6>,
pub unk: Option<[u32; 8]>,
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
#[br(import_raw(base_offset: u64))]
pub struct ModelV111 {
#[br(parse_with = parse_offset32_count32, offset = base_offset)]
#[xc3(offset_count(u32, u32))]
pub meshes: Vec<MeshV111>,
pub unk1: u32,
pub max_xyz: [f32; 3],
pub min_xyz: [f32; 3],
pub bounding_radius: f32,
pub unks1: [u32; 3], pub unk2: (u16, u16), pub unks: [u32; 3],
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
#[br(import_raw(base_offset: u64))]
pub struct ModelV112 {
#[br(parse_with = parse_offset32_count32, offset = base_offset)]
#[xc3(offset_count(u32, u32))]
pub meshes: Vec<MeshV112>,
pub unk1: u32,
pub max_xyz: [f32; 3],
pub min_xyz: [f32; 3],
pub bounding_radius: f32,
pub unks1: [u32; 3], pub unk2: (u16, u16), pub unks: [u32; 3],
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
pub struct MeshV111 {
pub flags1: u32,
pub flags2: MeshRenderFlags2,
pub vertex_buffer_index: u16,
pub index_buffer_index: u16,
pub index_buffer_index2: u16,
pub material_index: u16,
pub unk2: u32, pub unk3: u16, pub ext_mesh_index: u16,
pub unk4: u32, pub unk5: u16, pub lod_item_index: u8,
pub unk_mesh_index2: u8, pub alpha_table_index: u16,
pub unk6: u16, pub base_mesh_index: i32,
pub unk8: u32, pub unk9: u32, pub unk10: [u32; 4],
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
pub struct MeshV112 {
pub flags1: u32,
pub flags2: MeshRenderFlags2,
pub vertex_buffer_index: u16,
pub index_buffer_index: u16,
pub index_buffer_index2: u16,
pub material_index: u16,
pub unk2: u32, pub unk3: u16, pub ext_mesh_index: u16,
pub unk4: u32, pub unk5: u16, pub lod_item_index: u8,
pub unk_mesh_index2: u8, pub alpha_table_index: u16,
pub unk6: u16, pub base_mesh_index: i32,
pub unk8: u32, pub unk9: u32, }
#[bitsize(32)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(DebugBits, TryFromBits, BinRead, BinWrite, PartialEq, Clone, Copy)]
#[br(try_map = |x: u32| x.try_into().map_err(|e| format!("{e:?}")))]
#[bw(map = |&x| u32::from(x))]
pub struct MeshRenderFlags2 {
pub render_pass: MeshRenderPass,
pub unk5: u28,
}
#[bitsize(4)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, TryFromBits, PartialEq, Clone, Copy)]
pub enum MeshRenderPass {
Unk0 = 0,
Unk1 = 1,
Unk2 = 2,
Unk4 = 4, Unk8 = 8,
}
#[bitsize(32)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(DebugBits, FromBits, BinRead, BinWrite, PartialEq, Clone, Copy)]
#[br(map = u32::into)]
#[bw(map = |&x| u32::from(x))]
pub struct ModelsFlags {
pub unk1: bool,
pub has_model_unk8: bool,
pub unk3: bool,
pub unk4: bool,
pub unk5: bool,
pub unk6: bool,
pub has_model_unk7: bool,
pub unk8: bool,
pub unk9: bool,
pub unk10: bool,
pub has_morph_controllers: bool,
pub has_model_unk1: bool,
pub has_model_unk3: bool,
pub unk14: bool,
pub unk15: bool,
pub has_skinning: bool,
pub unk17: bool,
pub has_lod_data: bool,
pub has_alpha_table: bool,
pub unk20: bool,
pub unk21: bool,
pub unk22: bool,
pub unk23: bool,
pub unk24: bool,
pub unk25: bool,
pub unk26: bool,
pub unk27: bool,
pub unk28: bool,
pub unk29: bool,
pub unk30: bool,
pub unk31: bool,
pub unk32: bool,
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
#[br(import_raw(base_offset: u64))]
pub struct ExtMesh {
#[br(parse_with = parse_string_ptr32, offset = base_offset)]
#[xc3(offset(u32))]
pub name1: String,
#[br(parse_with = parse_string_ptr32, offset = base_offset)]
#[xc3(offset(u32))]
pub name2: String,
pub flags: ExtMeshFlags,
pub unk2: u16,
pub unk3: u32,
}
#[bitsize(16)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(DebugBits, FromBits, BinRead, BinWrite, PartialEq, Clone, Copy)]
#[br(map = u16::into)]
#[bw(map = |&x| u16::from(x))]
pub struct ExtMeshFlags {
pub unk1: bool, pub unk2: bool, pub unk3: bool, pub start_hidden: bool,
pub unk5: bool,
pub unk6: bool, pub unk: u10, }
#[binread]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
#[br(stream = r)]
#[xc3(base_offset)]
pub struct MorphControllers {
#[br(temp, try_calc = r.stream_position())]
base_offset: u64,
#[br(parse_with = parse_offset32_count32, args { offset: base_offset, inner: base_offset })]
#[xc3(offset_count(u32, u32))]
pub controllers: Vec<MorphController>,
pub unk1: u32,
pub unk: [u32; 3],
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
#[br(import_raw(base_offset: u64))]
pub struct MorphController {
#[br(parse_with = parse_string_ptr32, offset = base_offset)]
#[xc3(offset(u32))]
pub name1: String,
#[br(parse_with = parse_string_opt_ptr32, offset = base_offset)]
#[xc3(offset(u32))]
pub name2: Option<String>,
pub unk1: u16, pub unk2: u16, pub unk3: u16, pub unk4: u16,
pub unk: [u32; 3],
}
#[binread]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
#[br(stream = r)]
#[xc3(base_offset)]
pub struct ModelUnk3 {
#[br(temp, try_calc = r.stream_position())]
base_offset: u64,
#[br(parse_with = parse_count32_offset32, args { offset: base_offset, inner: base_offset })]
#[xc3(count_offset(u32, u32))]
pub items: Vec<ModelUnk3Item>,
pub unk: [u32; 4],
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, PartialEq, Clone)]
#[br(import_raw(base_offset: u64))]
pub struct ModelUnk3Item {
#[br(parse_with = parse_string_ptr32, offset = base_offset)]
#[xc3(offset(u32))]
pub name: String,
pub unk1: u32, pub unk2: u32,
#[br(parse_with = parse_offset32_count32, offset = base_offset)]
#[xc3(offset_count(u32, u32))]
pub unk3: Vec<u16>,
}
#[binread]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, Xc3Write, PartialEq, Clone)]
#[br(stream = r)]
#[xc3(base_offset)]
pub struct Unk8 {
#[br(temp, try_calc = r.stream_position())]
base_offset: u64,
pub unk1: u32,
#[br(parse_with = parse_count32_offset32)]
#[br(args { offset: base_offset, inner: base_offset })]
#[xc3(count_offset(u32, u32))]
pub unk2: Vec<Unk8Item>,
#[br(parse_with = parse_ptr32)]
#[br(args { offset: base_offset, inner: args! { count: unk2.len() } })]
#[xc3(offset(u32), align(16))]
pub unk3: Vec<[[f32; 4]; 4]>,
pub unk: [u32; 4],
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
#[br(import_raw(base_offset: u64))]
pub struct Unk8Item {
#[br(parse_with = parse_string_ptr32, offset = base_offset)]
#[xc3(offset(u32))]
pub name: String,
pub unk1: u32,
pub unk2: [[f32; 4]; 4],
pub unk3: u32,
}
#[binread]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
#[br(stream = r)]
#[xc3(base_offset)]
pub struct AlphaTable {
#[br(temp, try_calc = r.stream_position())]
base_offset: u64,
#[br(parse_with = parse_offset32_count32, offset = base_offset)]
#[xc3(offset_count(u32, u32))]
pub items: Vec<(u16, u16)>,
pub unks: [u32; 4],
}
#[binread]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
#[br(stream = r)]
#[xc3(base_offset)]
pub struct ModelUnk5 {
#[br(temp, try_calc = r.stream_position())]
base_offset: u64,
#[br(parse_with = parse_count32_offset32)]
#[br(args { offset: base_offset, inner: base_offset })]
#[xc3(count_offset(u32, u32))]
pub items: Vec<StringOffset32>,
pub unks: [u32; 4],
}
#[binread]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
#[br(stream = r)]
#[xc3(base_offset)]
pub struct ModelUnk6 {
#[br(temp, try_calc = r.stream_position())]
base_offset: u64,
#[br(parse_with = parse_count32_offset32, offset = base_offset)]
#[xc3(count_offset(u32, u32))]
pub items: Vec<[u32; 2]>,
pub unks: [u32; 4],
}
#[binread]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
#[br(stream = r)]
#[xc3(base_offset)]
pub struct ModelUnk7 {
#[br(temp, try_calc = r.stream_position())]
base_offset: u64,
#[br(parse_with = parse_count32_offset32, offset = base_offset)]
#[xc3(count_offset(u32, u32))]
pub items: Vec<[f32; 9]>,
pub unks: [u32; 4],
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
#[br(import_raw(base_offset: u64))]
pub struct ModelUnk8 {
#[br(parse_with = parse_offset32_count32, offset = base_offset)]
#[xc3(offset_count(u32, u32))]
pub unk1: Vec<[u32; 2]>,
#[br(parse_with = parse_offset32_count32, offset = base_offset)]
#[xc3(offset_count(u32, u32))]
pub unk2: Vec<[f32; 4]>,
pub unks: [u32; 2],
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
#[br(import_raw(base_offset: u64))]
pub struct ModelUnk9 {
pub unk1: u32,
#[br(args { unk1, base_offset})]
pub inner: ModelUnk9Inner,
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
#[br(import { unk1: u32, base_offset: u64 })]
pub enum ModelUnk9Inner {
#[br(pre_assert(unk1 != 10000))]
Unk0(ModelUnk9InnerUnk0),
#[br(pre_assert(unk1 == 10000))]
Unk1(#[br(args_raw(base_offset))] ModelUnk9InnerUnk1),
}
#[binread]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, Xc3Write, PartialEq, Clone)]
#[br(stream = r)]
#[xc3(base_offset)]
pub struct ModelUnk9InnerUnk0 {
#[br(temp, try_calc = r.stream_position().map(|p| p - 4))]
base_offset: u64,
#[br(parse_with = parse_offset32_count32, offset = base_offset)]
#[xc3(offset_count(u32, u32))]
pub items1: Vec<(u16, u16)>,
#[br(parse_with = parse_offset32_count32, offset = base_offset)]
#[xc3(offset_count(u32, u32))]
pub items2: Vec<(u16, u16)>,
pub unk: [u32; 4],
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
#[br(import_raw(base_offset: u64))]
pub struct ModelUnk9InnerUnk1 {
#[br(parse_with = parse_offset32_count32, offset = base_offset)]
#[xc3(offset_count(u32, u32))]
pub items: Vec<ModelUnk9Buffer>,
#[br(parse_with = parse_ptr32)]
#[br(args { offset: base_offset, inner: args! { count: model_unk9_buffer_length(&items) } })]
#[xc3(offset(u32))]
pub buffer: Vec<u8>,
pub unk2: u32,
pub unk: [u32; 3],
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
pub struct ModelUnk9Buffer {
pub offset: u32,
pub count: u32,
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
#[br(import_raw(base_offset: u64))]
pub struct ModelUnk10 {
#[br(parse_with = parse_offset32_count32, offset = base_offset)]
#[xc3(offset_count(u32, u32))]
pub unk1: Vec<u32>,
}
#[binread]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
#[br(stream = r)]
#[xc3(base_offset)]
pub struct ModelUnk11 {
#[br(temp, try_calc = r.stream_position())]
base_offset: u64,
#[br(parse_with = parse_count32_offset32, offset = base_offset)]
#[xc3(count_offset(u32, u32))]
pub unk1: Vec<[u32; 6]>,
#[br(parse_with = parse_count32_offset32, offset = base_offset)]
#[xc3(count_offset(u32, u32))]
pub unk2: Vec<[u32; 2]>,
pub unks: [u32; 4],
}
#[binread]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
#[br(stream = r)]
#[xc3(base_offset)]
pub struct ModelUnk12 {
#[br(temp, try_calc = r.stream_position())]
base_offset: u64,
#[br(parse_with = parse_offset32_count32, offset = base_offset)]
#[xc3(offset_count(u32, u32))]
pub items: Vec<ModelUnk12Item>,
#[br(parse_with = parse_offset32_count32, offset = base_offset)]
#[xc3(offset_count(u32, u32))]
pub indices: Vec<u32>,
pub unk2: u32,
pub unk: [u16; 22],
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
pub struct ModelUnk12Item {
pub unk1: [f32; 4],
pub unk2: [f32; 4],
pub unk3: [f32; 4],
pub unk4: [f32; 4],
}
#[binread]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, Xc3Write, PartialEq, Clone)]
#[br(stream = r)]
#[xc3(base_offset)]
pub struct ModelUnk1 {
#[br(temp, try_calc = r.stream_position())]
base_offset: u64,
#[br(parse_with = parse_offset32_count32)]
#[br(args { offset: base_offset, inner: base_offset })]
#[xc3(offset_count(u32, u32), align(4))]
pub items1: Vec<ModelUnk1Item1>,
#[br(parse_with = parse_offset32_count32, offset = base_offset)]
#[xc3(offset_count(u32, u32))]
pub items2: Vec<ModelUnk1Item2>,
#[br(parse_with = parse_ptr32)]
#[br(args { offset: base_offset, inner: args! { count: items1.len() }})]
#[xc3(offset(u32))]
pub items3: Vec<f32>,
pub unk1: u32,
#[br(parse_with = parse_offset32_count32, offset = base_offset)]
#[xc3(offset_count(u32, u32))]
pub items4: Vec<[u16; 10]>,
pub unk4: u32,
pub unk5: u32,
#[br(if(unk4 != 0 || unk5 != 0))]
#[br(args_raw(base_offset))]
pub extra: Option<ModelUnk1Extra>,
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
#[br(import_raw(base_offset: u64))]
pub struct ModelUnk1Extra {
#[br(parse_with = parse_opt_ptr32, offset = base_offset)]
#[xc3(offset(u32))]
pub unk_inner: Option<ModelUnk1Inner>,
pub unk: [u32; 4],
}
#[binread]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
#[br(stream = r)]
#[xc3(base_offset)]
pub struct ModelUnk1Inner {
#[br(temp, try_calc = r.stream_position())]
base_offset: u64,
#[br(parse_with = parse_offset32_count32, offset = base_offset)]
#[xc3(offset_count(u32, u32))]
pub items1: Vec<(u16, u16)>,
#[br(parse_with = parse_ptr32)]
#[br(args {
offset: base_offset,
inner: args! { count: items1.iter().map(|(i, j)| (*i + *j) as usize).max().unwrap_or_default() }
})]
#[xc3(offset(u32))]
pub items2: Vec<u16>,
pub unks: [u32; 5],
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
#[br(import_raw(base_offset: u64))]
pub struct ModelUnk1Item1 {
#[br(parse_with = parse_string_ptr32, offset = base_offset)]
#[xc3(offset(u32))]
pub name: String,
pub unk: [u32; 3],
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
pub struct ModelUnk1Item2 {
pub unk1: u16,
pub unk2: u16,
pub unk3: u32,
pub unk4: u32,
pub unk5: u32,
pub unk6: u32,
}
#[binread]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, Xc3Write, PartialEq, Clone)]
#[br(stream = r)]
#[xc3(base_offset)]
pub struct LodData {
#[br(temp, try_calc = r.stream_position())]
base_offset: u64,
pub unk1: u32,
#[br(parse_with = parse_offset32_count32, offset = base_offset)]
#[xc3(offset_count(u32, u32), align(16))]
pub items: Vec<LodItem>,
#[br(parse_with = parse_offset32_count32, offset = base_offset)]
#[xc3(offset_count(u32, u32))]
pub groups: Vec<LodGroup>,
pub unks: [u32; 4],
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
pub struct LodItem {
pub unk1: [u32; 4], pub unk2: f32, pub unk3: u8, pub index: u8, pub unk5: u8, pub unk6: u8, pub unk7: [u32; 2], }
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
pub struct LodGroup {
pub base_lod_index: u16,
pub lod_count: u16,
}
#[binread]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, Xc3Write, PartialEq, Clone)]
#[br(stream = r)]
#[xc3(base_offset)]
pub struct PackedTextures {
#[br(temp, try_calc = r.stream_position())]
base_offset: u64,
#[br(parse_with = parse_count32_offset32, args { offset: base_offset, inner: base_offset })]
#[xc3(count_offset(u32, u32))]
pub textures: Vec<PackedTexture>,
pub unk2: u32,
#[xc3(shared_offset)]
pub strings_offset: u32,
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
#[br(import_raw(base_offset: u64))]
pub struct PackedTexture {
pub usage: TextureUsage,
#[br(parse_with = parse_count32_offset32, offset = base_offset)]
#[xc3(count_offset(u32, u32), align(4096))]
pub mibl_data: Vec<u8>,
#[br(parse_with = parse_string_ptr32, offset = base_offset)]
#[xc3(offset(u32))]
pub name: String,
}
#[binread]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, Xc3Write, PartialEq, Clone)]
#[br(stream = r)]
#[xc3(base_offset)]
pub struct PackedExternalTextures<U>
where
U: Xc3Write + 'static,
for<'a> U: BinRead<Args<'a> = ()>,
for<'a> U::Offsets<'a>: Xc3WriteOffsets<Args = ()>,
{
#[br(temp, try_calc = r.stream_position())]
base_offset: u64,
#[br(parse_with = parse_count32_offset32, args { offset: base_offset, inner: base_offset })]
#[xc3(count_offset(u32, u32), align(2))]
pub textures: Vec<PackedExternalTexture<U>>,
pub unk2: u32,
#[xc3(shared_offset)]
pub strings_offset: u32,
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
#[br(import_raw(base_offset: u64))]
pub struct PackedExternalTexture<U>
where
U: Xc3Write + 'static,
for<'a> U: BinRead<Args<'a> = ()>,
for<'a> U::Offsets<'a>: Xc3WriteOffsets<Args = ()>,
{
pub usage: U,
pub length: u32,
pub offset: u32,
#[br(parse_with = parse_string_ptr32, offset = base_offset)]
#[xc3(offset(u32))]
pub name: String,
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, BinWrite, Clone, Copy, PartialEq, Eq, Hash)]
#[brw(repr(u32))]
pub enum TextureUsage {
Unk0 = 0,
Temp = 1048576,
Unk6 = 1074790400,
Nrm = 1179648,
Unk13 = 131072,
WavePlus = 136314882,
Col = 2097152,
Unk8 = 2162689,
Alp = 2228224,
Unk = 268435456,
Unk21 = 269615104,
Alp2 = 269484032,
Col2 = 270532608,
Unk11 = 270663680,
Unk9 = 272629760,
Alp3 = 273678336,
Nrm2 = 273809408,
Col3 = 274726912,
Unk3 = 274857984,
Unk2 = 275775488,
Unk20 = 287309824,
Unk17 = 3276800,
F01 = 403701762, Unk4 = 4194304,
Unk7 = 536870912,
Unk15 = 537001984,
Temp2 = 537919488,
Unk14 = 538050560,
Col4 = 538968064,
Alp4 = 539099136,
Unk12 = 540147712,
Unk18 = 65537,
Unk19 = 805306368,
Unk5 = 807403520,
Unk10 = 807534592,
VolTex = 811597824,
Unk16 = 811728896,
Unk22 = 6291456,
Unk23 = 5242880,
Unk24 = 69206016,
Unk25 = 7340032,
Unk26 = 3145728,
Unk27 = 73400320,
Unk28 = 35651584,
Unk29 = 34734080,
Unk30 = 34603008,
}
#[binread]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, Xc3Write, PartialEq, Clone)]
#[br(stream = r)]
#[xc3(base_offset)]
pub struct Skinning {
#[br(temp, try_calc = r.stream_position())]
base_offset: u64,
pub render_bone_count: u32,
pub bone_count: u32,
#[br(temp, restore_position)]
bones_offset: u32,
#[br(parse_with = parse_ptr32)]
#[br(args {
offset: base_offset,
inner: args! { count: bone_count as usize, inner: base_offset }
})]
#[xc3(offset(u32))]
pub bones: Vec<Bone>,
#[br(parse_with = parse_ptr32)]
#[br(args { offset: base_offset, inner: args! { count: bone_count as usize } })]
#[xc3(offset(u32), align(16))]
pub inverse_bind_transforms: Vec<[[f32; 4]; 4]>,
#[br(parse_with = parse_opt_ptr32)]
#[br(args { offset: base_offset, inner: args! { count: count_constraints(&bones) } })]
#[xc3(offset(u32))]
pub constraints: Option<Vec<BoneConstraint>>,
#[br(parse_with = parse_opt_ptr32)]
#[br(args { offset: base_offset, inner: args! { count: count_bounds(&bones) } })]
#[xc3(offset(u32))]
pub bounds: Option<Vec<BoneBounds>>,
#[br(parse_with = parse_count32_offset32, offset = base_offset)]
#[xc3(count_offset(u32, u32))]
pub bone_indices: Vec<u16>,
#[br(if(constraints.is_some()))]
#[br(args_raw(base_offset))]
pub unk_offset4: Option<SkinningUnkBones>,
#[br(if(bounds.is_some()))]
#[br(args_raw(base_offset))]
pub unk_offset5: Option<SkinningUnk5>,
#[br(if(!bone_indices.is_empty()))]
#[br(args_raw(base_offset))]
pub as_bone_data: Option<SkinningAsBoneData>,
#[br(if(bones_offset == 52))]
pub unk1: Option<[u32; 2]>,
#[br(if(bones_offset == 60))]
pub unk2: Option<[u32; 4]>,
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
#[br(import_raw(base_offset: u64))]
pub struct SkinningUnkBones {
#[br(parse_with = parse_opt_ptr32)]
#[br(args { offset: base_offset, inner: base_offset })]
#[xc3(offset(u32))]
pub unk_offset4: Option<UnkBones>,
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
#[br(import_raw(base_offset: u64))]
pub struct SkinningUnk5 {
#[br(parse_with = parse_opt_ptr32, offset = base_offset)]
#[xc3(offset(u32))]
pub unk_offset5: Option<SkeletonUnk5>,
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
#[br(import_raw(base_offset: u64))]
pub struct SkinningAsBoneData {
#[br(parse_with = parse_opt_ptr32, args { offset: base_offset, inner: base_offset })]
#[xc3(offset(u32))]
pub as_bone_data: Option<AsBoneData>,
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
pub struct BoneConstraint {
pub fixed_offset: [f32; 3],
pub max_distance: f32,
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
pub struct BoneBounds {
pub center: [f32; 4],
pub size: [f32; 4],
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
#[br(import_raw(base_offset: u64))]
pub struct Bone {
#[br(parse_with = parse_string_ptr32, offset = base_offset)]
#[xc3(offset(u32))]
pub name: String,
pub bounds_radius: f32,
pub flags: BoneFlags,
pub constraint_index: u8,
pub parent_index: u8,
pub bounds_index: u32,
pub unk: [u32; 2],
}
#[bitsize(16)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(DebugBits, FromBits, BinRead, BinWrite, PartialEq, Clone, Copy)]
#[br(map = u16::into)]
#[bw(map = |&x| u16::from(x))]
pub struct BoneFlags {
pub fixed_offset_constraint: bool,
pub bounds_offset: bool,
pub distance_constraint: bool,
pub no_camera_overlap: bool,
pub unk: u12,
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
#[br(import_raw(base_offset: u64))]
pub struct UnkBones {
#[br(parse_with = parse_offset32_count32, offset = base_offset)]
#[xc3(offset_count(u32, u32))]
pub bones: Vec<UnkBone>,
#[br(parse_with = parse_ptr32)]
#[br(args { offset: base_offset, inner: args! { count: bones.len() }})]
#[xc3(offset(u32), align(16))]
pub unk_offset: Vec<[[f32; 4]; 4]>,
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
pub struct UnkBone {
pub unk1: u32,
pub bone_index: u16,
pub parent_index: u16,
pub unks: [u32; 7],
}
#[binread]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, Xc3Write, PartialEq, Clone)]
#[br(stream = r)]
#[xc3(base_offset)]
pub struct SkeletonUnk5 {
#[br(temp, try_calc = r.stream_position())]
base_offset: u64,
#[br(parse_with = parse_count32_offset32)]
#[br(args { offset: base_offset, inner: base_offset })]
#[xc3(count_offset(u32, u32))]
pub unk1: Vec<SkeletonUnk5Unk1>,
#[br(parse_with = parse_opt_ptr32, offset = base_offset)]
#[xc3(offset(u32))]
pub unk_offset: Option<[f32; 12]>,
pub unk: [u32; 5],
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
#[br(import_raw(base_offset: u64))]
pub struct SkeletonUnk5Unk1 {
pub unk1: [[f32; 4]; 4],
pub unk2: u32,
#[br(parse_with = parse_count32_offset32, offset = base_offset)]
#[xc3(count_offset(u32, u32))]
pub unk3: Vec<SkeletonUnk5Unk1Unk3>,
#[br(parse_with = parse_count32_offset32, offset = base_offset)]
#[xc3(count_offset(u32, u32))]
pub unk4: Vec<u32>,
pub unk7: [f32; 15],
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
pub struct SkeletonUnk5Unk1Unk3 {
pub unk1: f32,
pub unk2: u16, pub unk3: u16, }
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
#[br(import_raw(base_offset: u64))]
pub struct AsBoneData {
#[br(parse_with = parse_offset32_count32, offset = base_offset)]
#[xc3(offset_count(u32, u32))]
pub bones: Vec<AsBone>,
#[br(parse_with = parse_offset32_count32, offset = base_offset)]
#[xc3(offset_count(u32, u32))]
pub values: Vec<AsBoneValue>,
#[br(parse_with = parse_ptr32)]
#[br(args { offset: base_offset, inner: args! { count: bones.len() }})]
#[xc3(offset(u32), align(16))]
pub transforms: Vec<AsBoneTransform>,
pub unk3: u32,
pub unk: [u32; 2],
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
pub struct AsBone {
pub bone_index: u16,
pub parent_index: u16,
pub unk_end_index: u16, pub unk_start_index: u16, pub unk1: u16,
pub unk2: u16,
pub value_count: u16,
pub value_start_index: u16,
pub translation: [f32; 3],
pub unk5: [f32; 6], pub rotation_quaternion: [f32; 4],
pub unk6: [f32; 3],
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
pub struct AsBoneValue {
unk1: [f32; 4],
unk2: [f32; 4],
unk3: [f32; 4],
unk4: [f32; 2],
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
pub struct AsBoneTransform {
pub unk1: [[f32; 4]; 4],
pub unk2: [[f32; 4]; 4],
pub unk3: [[f32; 4]; 4],
}
#[binread]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, Xc3Write, PartialEq, Clone)]
#[br(stream = r)]
#[xc3(base_offset)]
pub struct Unk1 {
#[br(temp, try_calc = r.stream_position())]
base_offset: u64,
#[br(parse_with = parse_count32_offset32, offset = base_offset)]
#[xc3(count_offset(u32, u32))]
pub unk1: Vec<Unk1Unk1>,
#[br(parse_with = parse_count32_offset32, offset = base_offset)]
#[xc3(count_offset(u32, u32))]
pub unk2: Vec<Unk1Unk2>,
#[br(parse_with = parse_count32_offset32, offset = base_offset)]
#[xc3(count_offset(u32, u32))]
pub unk3: Vec<Unk1Unk3>,
#[br(parse_with = parse_count32_offset32, offset = base_offset)]
#[xc3(count_offset(u32, u32))]
pub unk4: Vec<Unk1Unk4>,
pub unk: [u32; 4],
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
pub struct Unk1Unk1 {
pub index: u16,
pub unk2: u16, }
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
pub struct Unk1Unk2 {
pub unk1: u16, pub index: u16,
pub unk3: u16,
pub unk4: u16,
pub unk5: u32, }
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
pub struct Unk1Unk3 {
pub unk1: u16,
pub unk2: u16,
pub unk3: u32,
pub unk4: u16,
pub unk5: u16,
pub unk6: u16,
pub unk7: u16,
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
pub struct Unk1Unk4 {
pub unk1: f32,
pub unk2: f32,
pub unk3: f32,
pub unk4: u32,
}
xc3_write_binwrite_impl!(
ParamType,
RenderPassType,
StateFlags,
ModelsFlags,
SamplerFlags,
TextureUsage,
ExtMeshFlags,
MeshRenderFlags2,
MaterialFlags,
MaterialRenderFlags,
BoneFlags
);
impl Xc3WriteOffsets for SkinningOffsets<'_> {
type Args = ();
fn write_offsets<W: std::io::Write + std::io::Seek>(
&self,
writer: &mut W,
_base_offset: u64,
data_ptr: &mut u64,
endian: xc3_write::Endian,
_args: Self::Args,
) -> xc3_write::Xc3Result<()> {
let base_offset = self.base_offset;
let bones = self.bones.write(writer, base_offset, data_ptr, endian)?;
if !self.bone_indices.data.is_empty() {
self.bone_indices
.write_full(writer, base_offset, data_ptr, endian, ())?;
}
self.inverse_bind_transforms
.write_full(writer, base_offset, data_ptr, endian, ())?;
self.constraints
.write_full(writer, base_offset, data_ptr, endian, ())?;
self.bounds
.write_full(writer, base_offset, data_ptr, endian, ())?;
self.unk_offset4
.write_offsets(writer, base_offset, data_ptr, endian, ())?;
self.as_bone_data
.write_offsets(writer, base_offset, data_ptr, endian, ())?;
self.unk_offset5
.write_offsets(writer, base_offset, data_ptr, endian, ())?;
for bone in bones.0 {
bone.name
.write_full(writer, base_offset, data_ptr, endian, ())?;
}
Ok(())
}
}
impl Xc3WriteOffsets for ModelUnk1Offsets<'_> {
type Args = ();
fn write_offsets<W: std::io::Write + std::io::Seek>(
&self,
writer: &mut W,
_base_offset: u64,
data_ptr: &mut u64,
endian: xc3_write::Endian,
_args: Self::Args,
) -> xc3_write::Xc3Result<()> {
let base_offset = self.base_offset;
let items1 = self.items1.write(writer, base_offset, data_ptr, endian)?;
self.items3
.write_full(writer, base_offset, data_ptr, endian, ())?;
if !self.items2.data.is_empty() {
self.items2
.write_full(writer, base_offset, data_ptr, endian, ())?;
}
if !self.items4.data.is_empty() {
self.items4
.write_full(writer, base_offset, data_ptr, endian, ())?;
}
for item in items1.0 {
item.name
.write_full(writer, base_offset, data_ptr, endian, ())?;
}
self.extra
.write_offsets(writer, base_offset, data_ptr, endian, ())?;
Ok(())
}
}
impl Xc3WriteOffsets for LodDataOffsets<'_> {
type Args = ();
fn write_offsets<W: std::io::Write + std::io::Seek>(
&self,
writer: &mut W,
_base_offset: u64,
data_ptr: &mut u64,
endian: xc3_write::Endian,
_args: Self::Args,
) -> xc3_write::Xc3Result<()> {
let base_offset = self.base_offset;
self.groups
.write_full(writer, base_offset, data_ptr, endian, ())?;
self.items
.write_full(writer, base_offset, data_ptr, endian, ())?;
Ok(())
}
}
impl Xc3WriteOffsets for ModelsV112Offsets<'_> {
type Args = ();
fn write_offsets<W: std::io::Write + std::io::Seek>(
&self,
writer: &mut W,
_base_offset: u64,
data_ptr: &mut u64,
endian: xc3_write::Endian,
_args: Self::Args,
) -> xc3_write::Xc3Result<()> {
let base_offset = self.base_offset;
self.models
.write_full(writer, base_offset, data_ptr, endian, ())?;
self.skinning
.write_full(writer, base_offset, data_ptr, endian, ())?;
if !self.ext_meshes.data.is_empty() {
self.ext_meshes
.write_full(writer, base_offset, data_ptr, endian, ())?;
}
self.model_unk8
.write_full(writer, base_offset, data_ptr, endian, ())?;
self.morph_controllers
.write_full(writer, base_offset, data_ptr, endian, ())?;
self.lod_data
.write_full(writer, base_offset, data_ptr, endian, ())?;
self.model_unk7
.write_full(writer, base_offset, data_ptr, endian, ())?;
self.model_unk11
.write_full(writer, base_offset, data_ptr, endian, ())?;
self.model_unk1
.write_full(writer, base_offset, data_ptr, endian, ())?;
self.model_unk12
.write_full(writer, base_offset, data_ptr, endian, ())?;
self.alpha_table
.write_full(writer, base_offset, data_ptr, endian, ())?;
self.model_unk3
.write_full(writer, base_offset, data_ptr, endian, ())?;
self.model_unk9
.write_full(writer, base_offset, data_ptr, endian, ())?;
self.extra
.write_offsets(writer, base_offset, data_ptr, endian, ())?;
Ok(())
}
}
impl Xc3WriteOffsets for TechniqueOffsets<'_> {
type Args = ();
fn write_offsets<W: std::io::Write + std::io::Seek>(
&self,
writer: &mut W,
base_offset: u64,
data_ptr: &mut u64,
endian: xc3_write::Endian,
_args: Self::Args,
) -> xc3_write::Xc3Result<()> {
self.attributes
.write_full(writer, base_offset, data_ptr, endian, ())?;
if !self.textures.data.is_empty() {
self.textures
.write_full(writer, base_offset, data_ptr, endian, ())?;
}
self.uniform_blocks
.write_full(writer, base_offset, data_ptr, endian, ())?;
self.parameters
.write_full(writer, base_offset, data_ptr, endian, ())?;
self.unk15
.write_full(writer, base_offset, data_ptr, endian, ())?;
*data_ptr += self.parameters.data.len() as u64 * 16;
Ok(())
}
}
impl Xc3WriteOffsets for MaterialsOffsets<'_> {
type Args = ();
fn write_offsets<W: std::io::Write + std::io::Seek>(
&self,
writer: &mut W,
_base_offset: u64,
data_ptr: &mut u64,
endian: xc3_write::Endian,
_args: Self::Args,
) -> xc3_write::Xc3Result<()> {
let base_offset = self.base_offset;
let materials = self
.materials
.write(writer, base_offset, data_ptr, endian)?;
self.work_values
.write_full(writer, base_offset, data_ptr, endian, ())?;
self.shader_vars
.write_full(writer, base_offset, data_ptr, endian, ())?;
for material in &materials.0 {
material
.techniques
.write_full(writer, base_offset, data_ptr, endian, ())?;
}
for material in &materials.0 {
material
.textures
.write_full(writer, base_offset, data_ptr, endian, ())?;
}
if !self.alpha_test_textures.data.is_empty() {
self.alpha_test_textures
.write_full(writer, base_offset, data_ptr, endian, ())?;
}
self.callbacks
.write_full(writer, base_offset, data_ptr, endian, ())?;
self.material_unk2
.write_full(writer, base_offset, data_ptr, endian, ())?;
self.fur_shells
.write_full(writer, base_offset, data_ptr, endian, ())?;
self.samplers
.write_full(writer, base_offset, data_ptr, endian, ())?;
self.unk6
.write_full(writer, base_offset, data_ptr, endian, ())?;
self.unk5
.write_offsets(writer, base_offset, data_ptr, endian, ())?;
self.techniques
.write_full(writer, base_offset, data_ptr, endian, ())?;
for material in &materials.0 {
material
.name
.write_full(writer, base_offset, data_ptr, endian, ())?;
}
Ok(())
}
}
impl Xc3WriteOffsets for MxmdV112Offsets<'_> {
type Args = ();
fn write_offsets<W: std::io::Write + std::io::Seek>(
&self,
writer: &mut W,
base_offset: u64,
data_ptr: &mut u64,
endian: xc3_write::Endian,
_args: Self::Args,
) -> xc3_write::Xc3Result<()> {
self.models
.write_full(writer, base_offset, data_ptr, endian, ())?;
self.unk8
.write_full(writer, base_offset, data_ptr, endian, ())?;
self.materials
.write_full(writer, base_offset, data_ptr, endian, ())?;
self.streaming
.write_full(writer, base_offset, data_ptr, endian, ())?;
vec![0u8; (data_ptr.next_multiple_of(16) - *data_ptr) as usize]
.xc3_write(writer, endian)?;
*data_ptr = (*data_ptr).max(writer.stream_position()?);
self.unk1
.write_full(writer, base_offset, data_ptr, endian, ())?;
self.vertex_data
.write_full(writer, base_offset, data_ptr, endian, ())?;
self.spch
.write_full(writer, base_offset, data_ptr, endian, ())?;
self.packed_textures
.write_full(writer, base_offset, data_ptr, endian, ())?;
Ok(())
}
}
impl Xc3WriteOffsets for Unk1Offsets<'_> {
type Args = ();
fn write_offsets<W: std::io::Write + std::io::Seek>(
&self,
writer: &mut W,
_base_offset: u64,
data_ptr: &mut u64,
endian: xc3_write::Endian,
_args: Self::Args,
) -> xc3_write::Xc3Result<()> {
let base_offset = self.base_offset;
self.unk1
.write_full(writer, base_offset, data_ptr, endian, ())?;
self.unk2
.write_full(writer, base_offset, data_ptr, endian, ())?;
self.unk3
.write_full(writer, base_offset, data_ptr, endian, ())?;
if !self.unk4.data.is_empty() {
self.unk4
.write_full(writer, base_offset, data_ptr, endian, ())?;
}
Ok(())
}
}
impl Xc3WriteOffsets for ModelUnk3ItemOffsets<'_> {
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<()> {
self.unk3
.write_full(writer, base_offset, data_ptr, endian, ())?;
self.name
.write_full(writer, base_offset, data_ptr, endian, ())?;
Ok(())
}
}
impl Xc3WriteOffsets for FurShellsOffsets<'_> {
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<()> {
self.params
.write_full(writer, base_offset, data_ptr, endian, ())?;
self.material_param_indices
.write_full(writer, base_offset, data_ptr, endian, ())?;
Ok(())
}
}
impl Xc3WriteOffsets for PackedTexturesOffsets<'_> {
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 base_offset = self.base_offset;
let textures = self.textures.write(writer, base_offset, data_ptr, endian)?;
self.strings_offset
.write_full(writer, base_offset, data_ptr, endian, ())?;
for texture in &textures.0 {
texture
.name
.write_full(writer, base_offset, data_ptr, endian, ())?;
}
for texture in &textures.0 {
texture
.mibl_data
.write_full(writer, base_offset, data_ptr, endian, ())?;
}
Ok(())
}
}
impl<U> Xc3WriteOffsets for PackedExternalTexturesOffsets<'_, U>
where
U: Xc3Write + 'static,
for<'b> U: BinRead<Args<'b> = ()>,
for<'b> U::Offsets<'b>: Xc3WriteOffsets<Args = ()>,
{
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 base_offset = self.base_offset;
let textures = self.textures.write(writer, base_offset, data_ptr, endian)?;
self.strings_offset
.write_full(writer, base_offset, data_ptr, endian, ())?;
for texture in &textures.0 {
texture
.name
.write_full(writer, base_offset, data_ptr, endian, ())?;
}
Ok(())
}
}
impl Xc3WriteOffsets for SkeletonUnk5Offsets<'_> {
type Args = ();
fn write_offsets<W: std::io::Write + std::io::Seek>(
&self,
writer: &mut W,
_base_offset: u64,
data_ptr: &mut u64,
endian: xc3_write::Endian,
_args: Self::Args,
) -> xc3_write::Xc3Result<()> {
let base_offset = self.base_offset;
let unk1 = self.unk1.write(writer, base_offset, data_ptr, endian)?;
for u in &unk1.0 {
u.unk3
.write_full(writer, base_offset, data_ptr, endian, ())?;
}
for u in &unk1.0 {
u.unk4
.write_full(writer, base_offset, data_ptr, endian, ())?;
}
self.unk_offset
.write_full(writer, base_offset, data_ptr, endian, ())?;
Ok(())
}
}
impl Xc3WriteOffsets for Unk8Offsets<'_> {
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 base_offset = self.base_offset;
let unk2 = self.unk2.write(writer, base_offset, data_ptr, endian)?;
self.unk3
.write_full(writer, base_offset, data_ptr, endian, ())?;
for u in unk2.0 {
u.name
.write_full(writer, base_offset, data_ptr, endian, ())?;
}
Ok(())
}
}
impl Xc3WriteOffsets for ModelUnk9InnerUnk0Offsets<'_> {
type Args = ();
fn write_offsets<W: std::io::Write + std::io::Seek>(
&self,
writer: &mut W,
_base_offset: u64,
data_ptr: &mut u64,
endian: xc3_write::Endian,
args: Self::Args,
) -> xc3_write::Xc3Result<()> {
let base_offset = self.base_offset.saturating_sub(4);
if !self.items1.data.is_empty() {
self.items1
.write_full(writer, base_offset, data_ptr, endian, args)?;
}
if !self.items2.data.is_empty() {
self.items2
.write_full(writer, base_offset, data_ptr, endian, args)?;
}
Ok(())
}
}
impl Xc3WriteOffsets for MaterialCallbacksOffsets<'_> {
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<()> {
self.work_callbacks
.write_full(writer, base_offset, data_ptr, endian, ())?;
self.unk1
.write_full(writer, base_offset, data_ptr, endian, ())?;
self.material_indices
.write_full(writer, base_offset, data_ptr, endian, ())?;
Ok(())
}
}
fn count_constraints(bones: &[Bone]) -> usize {
bones
.iter()
.map(|b| {
if b.flags.distance_constraint() || b.flags.fixed_offset_constraint() {
b.constraint_index as usize + 1
} else {
0
}
})
.max()
.unwrap_or_default()
}
fn count_bounds(bones: &[Bone]) -> usize {
bones
.iter()
.map(|b| {
if b.flags.bounds_offset() {
b.bounds_index as usize + 1
} else {
0
}
})
.max()
.unwrap_or_default()
}
fn model_unk9_buffer_length(buffers: &[ModelUnk9Buffer]) -> usize {
buffers
.iter()
.max_by_key(|b| b.offset)
.map(|b| b.offset as usize + b.count as usize * 48)
.unwrap_or_default()
}