XPlor/definitions/volition/asm.xscript
njohnson 7b1f5d34a1 Consolidate XScript definitions with byte order inheritance
- Volition VPP: Unified BE/LE types using inheritance pattern
- THQA PAK: Child types now inherit byte order from parent
- Various XScript definition updates and fixes

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-11 16:08:46 -05:00

144 lines
3.5 KiB
Plaintext

// Volition ASM Assembly/Manifest Format
// Used by: Saints Row 3/4, Red Faction series
// Magic: 0xBEEFFEED (LE) or 0xEDFEEFBE (BE)
// Contains asset container and primitive definitions
// Root dispatcher - detects endianness and delegates
type volition_asm ui("Volition ASM File", root) byteorder LE
{
criteria {
require _ext == "asm_pc" || _ext == "asm" || _ext == "asm_xbox2";
le_magic = u32at(0);
require le_magic == 0xBEEFFEED || le_magic == 0xEDFEEFBE;
}
// Detect endianness from magic
magic_check = u32at(0);
if (magic_check == 0xEDFEEFBE) {
set_name("ASM File (Xbox 360)");
parse_here("volition_asm_be");
} else {
set_name("ASM File (PC)");
parse_here("volition_asm_impl");
}
}
// BE wrapper - explicit byteorder needed to override inherited LE
type volition_asm_be ui("ASM BE") byteorder BE
{
parse_here("volition_asm_impl");
}
// Shared implementation - inherits byteorder from caller
type volition_asm_impl ui("ASM")
{
u32 magic ui("Magic");
u16 version ui("Version");
u16 container_count ui("Container Count");
// Version 8+ has type registries
if (version >= 8) {
u32 allocator_type_count ui("Allocator Type Count");
alloc_idx = 0;
repeat(allocator_type_count) {
u16 at_name_len;
at_name = ascii(read(at_name_len));
u8 at_id;
alloc_idx = alloc_idx + 1;
}
u32 primitive_type_count ui("Primitive Type Count");
prim_idx = 0;
repeat(primitive_type_count) {
u16 pt_name_len;
pt_name = ascii(read(pt_name_len));
u8 pt_id;
prim_idx = prim_idx + 1;
}
u32 container_type_count ui("Container Type Count");
cont_idx = 0;
repeat(container_type_count) {
u16 ct_name_len;
ct_name = ascii(read(ct_name_len));
u8 ct_id;
cont_idx = cont_idx + 1;
}
}
// Parse container entries
c_idx = 0;
repeat(container_count) {
u16 c_name_len;
c_name = ascii(read(c_name_len));
u8 c_type;
u16 c_flags;
u16 c_primitive_count;
u32 c_data_offset;
if (version >= 10) {
u16 c_parent_len;
c_parent = ascii(read(c_parent_len));
}
u32 c_extra_len;
if (c_extra_len > 0) {
c_extra = read(c_extra_len);
}
if (version < 9) {
i32 c_old_size;
}
u32 c_compressed_size;
has_sizes = ((c_flags & 0x80) != 0) || (version >= 11);
if (has_sizes) {
sizes_idx = 0;
repeat(c_primitive_count) {
if (version >= 9) {
i32 ps_cpu_size;
}
i32 ps_gpu_size;
sizes_idx = sizes_idx + 1;
}
}
// Parse primitives
prim_idx = 0;
repeat(c_primitive_count) {
u16 p_name_len;
p_name = ascii(read(p_name_len));
u8 p_type;
u8 p_allocator;
u8 p_flags;
u8 p_split_index;
i32 p_cpu_size;
i32 p_gpu_size;
u8 p_unknown7;
prim_idx = prim_idx + 1;
}
// Create container child
ctx_set("_asm_container_name", c_name);
ctx_set("_asm_container_prim_count", c_primitive_count);
dummy = bytesat(0, 1);
container_child = dummy |> parse volition_asm_container;
push("containers", container_child);
c_idx = c_idx + 1;
}
total_containers = container_count ui("Total Containers");
file_size = size() ui("File Size");
}
// Container child - inherits byteorder from parent
type volition_asm_container ui("Container")
{
container_name = ctx_get("_asm_container_name");
set_name(container_name);
prim_count = ctx_get("_asm_container_prim_count");
primitives = prim_count ui("Primitives");
}