// RAD Resource Descriptor Format - THQ Australia Engine // Big-endian version (Xbox 360, Wii): "rad0" magic // Little-endian version (Original Xbox): "0dar" magic // Big-endian RAD (Xbox 360, Wii) type thqa_rad ui("THQA RAD Resource", root) byteorder BE { criteria { require ascii(bytesat(0, 4)) == "rad0"; } // Header (24 bytes) magic = ascii(read(4)) ui("Magic"); u32 flags ui("Flags"); u32 data_size ui("Data Section Size"); u32 header_size ui("Header Size"); u32 section_info_offset ui("Section Info Offset"); u32 ptch_section_offset ui("Ptch Section Offset"); // Read null-terminated filename filename = cstring() ui("Filename"); set_name(filename); // Read null-terminated section name section_name = cstring() ui("Section Name"); // Extract embedded data section if present if (data_size > 0 && header_size < section_info_offset) { seek(header_size); data_magic = ascii(bytesat(header_size, 4)); if (data_magic == "g4rc") { data_block = read(data_size); ctx_set("_thqa_rad_data_name", filename + " [Data]"); data_child = data_block |> parse thqa_rad_g4rc_data; push("resources", data_child); } else if (data_magic == "dsrc") { data_block = read(data_size); ctx_set("_thqa_rad_data_name", filename + " [DSRC]"); data_child = data_block |> parse thqa_rad_dsrc_data; push("resources", data_child); } else { data_block = read(data_size); ctx_set("_thqa_rad_data_name", filename + " [Raw Data]"); data_child = data_block |> parse thqa_rad_raw_data; push("resources", data_child); } } // Seek to section info block seek(section_info_offset); u32 info_flags ui("Info Flags"); u32 info_reserved1 ui("Info Reserved 1"); u32 info_reserved2 ui("Info Reserved 2"); u32 info_count1 ui("Info Count 1"); u32 info_count2 ui("Info Count 2"); u32 info_data_size ui("Info Data Size"); u32 info_total_size ui("Info Total Size"); // Seek to ptch section seek(ptch_section_offset); ptch_marker = ascii(read(4)) ui("Ptch Marker"); u32 ptch_reserved1 ui("Ptch Reserved 1"); u32 ptch_reserved2 ui("Ptch Reserved 2"); u32 ptch_offset_count ui("Ptch Offset Count"); if (ptch_offset_count > 0 && ptch_offset_count < 10000) { repeat(ptch_offset_count) { u32 _offset; } } // Look for expl/done sections if (pos() + 4 <= size()) { next_marker = ascii(read(4)); if (next_marker == "expl") { expl_marker = next_marker ui("Expl Marker"); u32 expl_reserved1 ui("Expl Reserved 1"); u32 expl_flags ui("Expl Flags"); } else if (next_marker == "done") { done_marker = next_marker ui("Done Marker"); } } file_size_total = size() ui("Total File Size"); } // Little-endian RAD (Original Xbox) type thqa_rad_le ui("THQA RAD Resource", root) byteorder LE { criteria { require ascii(bytesat(0, 4)) == "0dar"; } magic = ascii(read(4)) ui("Magic"); u32 flags ui("Flags"); u32 data_size ui("Data Size"); u32 header_size ui("Header Size"); u32 strings_offset ui("Strings Offset"); u32 strings_size ui("Strings Size"); // Read resource name if (strings_offset > 0 && strings_offset < size()) { seek(strings_offset); resource_name = cstring() ui("Resource Name"); set_name(resource_name); } // Look for patch blocks seek(header_size); if (pos() + 4 <= size()) { block_magic = ascii(bytesat(pos(), 4)); if (block_magic == "hctp") { patch_magic = ascii(read(4)) ui("Patch Magic"); } } file_size = size() ui("Total File Size"); } // Helper types for RAD data blocks // These inherit byteorder from parent (thqa_rad) type thqa_rad_g4rc_data ui("RAD G4RC Data") { set_name(ctx_get("_thqa_rad_data_name")); data_size = size() ui("Size"); data = read(size()); } type thqa_rad_dsrc_data ui("RAD DSRC Data") { set_name(ctx_get("_thqa_rad_data_name")); data_size = size() ui("Size"); data = read(size()); } type thqa_rad_raw_data ui("RAD Raw Data") { set_name(ctx_get("_thqa_rad_data_name")); data_size = size() ui("Size"); data = read(size()); }