XPlor/definitions/volition/anim.xscript
njohnson 908100f487 Enhance Volition format definitions for Saints Row series
Major improvements to VPP, PEG, and ASM parsers:

vpp.xscript:
- Support all VPP versions (4-10) for Saints Row 1-4 and Red Faction
- Add container type detection (str2, packfile, etc.)
- Improved compression handling (zlib, LZO, auto-detection)
- Better recursive parsing of nested archives

peg.xscript:
- Full PEG texture container parsing
- Support for multiple texture formats (DXT1, DXT3, DXT5, etc.)
- Xbox 360 and PC format variants

asm.xscript:
- Animation state machine container parsing

New format definitions:
- anim.xscript: Animation data
- audio.xscript: Audio containers (bank files)
- mesh.xscript: 3D mesh geometry
- morph.xscript: Morph targets
- rig.xscript: Skeletal rigs
- sim.xscript: Simulation data
- zone.xscript: Level zone data

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-12 20:53:59 -05:00

90 lines
2.6 KiB
Plaintext

// Volition Animation Format (.anim_pc)
// Used by: Saints Row 3/4, Red Faction series
// Crunched animation with keyframe data
type volition_anim ui("Volition Animation", root) byteorder LE
{
criteria {
require _ext == "anim_pc" || _ext == "anim_xbox2" || _ext == "anim_ps3";
// Basic sanity: version byte should be reasonable (1-50)
ver = u8at(4);
require ver > 0 && ver < 50;
}
is_xbox = ends_with(_ext, "xbox2");
is_ps3 = ends_with(_ext, "ps3");
if (is_xbox || is_ps3) {
set_name("Animation (Console)");
parse_here("volition_anim_be");
} else {
set_name("Animation (PC)");
parse_here("volition_anim_impl");
}
}
type volition_anim_be ui("Animation") byteorder BE
{
parse_here("volition_anim_impl");
}
type volition_anim_impl ui("Animation")
{
i32 anim_id ui("Animation ID");
u8 version ui("Version");
u8 flags ui("Flags");
u16 end_frame ui("End Frame");
u8 ramp_in ui("Ramp In");
u8 ramp_out ui("Ramp Out");
u8 num_bones ui("Bone Count");
u8 num_rig_bones ui("Rig Bone Count");
// Total rotation quaternion
f32 rot_x ui("Total Rot X");
f32 rot_y ui("Total Rot Y");
f32 rot_z ui("Total Rot Z");
f32 rot_w ui("Total Rot W");
// Total translation
f32 trans_x ui("Total Trans X");
f32 trans_y ui("Total Trans Y");
f32 trans_z ui("Total Trans Z");
// Decode flags
has_packed = (flags & 0x01) != 0;
has_time_shorts = (flags & 0x02) != 0;
has_delta_times = (flags & 0x04) != 0;
has_motion = (flags & 0x08) != 0;
has_morph = (flags & 0x10) != 0;
has_long_trans = (flags & 0x20) != 0;
has_weight_keys = (flags & 0x40) != 0;
has_short_counts = (flags & 0x80) != 0;
flags_desc = "";
if (has_packed) { flags_desc = flags_desc + "PACKED "; }
if (has_time_shorts) { flags_desc = flags_desc + "TIME_SHORTS "; }
if (has_delta_times) { flags_desc = flags_desc + "DELTA_TIMES "; }
if (has_motion) { flags_desc = flags_desc + "MOTION "; }
if (has_morph) { flags_desc = flags_desc + "MORPH "; }
if (has_long_trans) { flags_desc = flags_desc + "LONG_TRANS "; }
if (has_weight_keys) { flags_desc = flags_desc + "WEIGHT_KEYS "; }
if (has_short_counts) { flags_desc = flags_desc + "SHORT_COUNTS "; }
flag_display = trim(flags_desc) ui("Flag Names");
file_size = size() ui("File Size");
}
// Nested type for VPP
type volition_anim_nested ui("Animation") byteorder LE
{
file_name = ctx_get("_vpp_file_name");
set_name(file_name);
is_xbox = ctx_get("_vpp_is_xbox");
is_ps3 = ctx_get("_vpp_is_ps3");
if (is_xbox || is_ps3) {
parse_here("volition_anim_be");
} else {
parse_here("volition_anim_impl");
}
}