- 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>
144 lines
3.5 KiB
Plaintext
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");
|
|
}
|