// String Table format - THQ Australia Engine // Magic: "bats" // Avatar/Wii: 12-byte entries, ASCII strings // SpongeBob/Xbox: 16-byte entries, UTF-16LE strings // Avatar-style string table (12-byte entries, ASCII) type thqa_str ui("String Table", root) byteorder LE { criteria { require ascii(bytesat(0, 4)) == "bats"; } magic = ascii(read(4)) ui("Magic"); u32 language_code ui("Language Code"); u32 entry_count ui("Entry Count"); // Entries are 12 bytes each entries_end = 12 + (entry_count * 12); string_data_start = entries_end + 8; // First pass: collect all string offsets idx = 0; repeat(entry_count) { u16 e_string_id; u16 e_lang; u32 e_string_offset; u32 e_reference; ctx_set("_thqa_str_entry_" + idx + "_id", e_string_id); ctx_set("_thqa_str_entry_" + idx + "_lang", e_lang); ctx_set("_thqa_str_entry_" + idx + "_offset", e_string_offset); ctx_set("_thqa_str_entry_" + idx + "_ref", e_reference); idx = idx + 1; } // Skip srts marker and size skip(8); // Second pass: read strings and create table rows idx = 0; repeat(entry_count) { e_string_id = ctx_get("_thqa_str_entry_" + idx + "_id"); e_lang = ctx_get("_thqa_str_entry_" + idx + "_lang"); e_string_offset = ctx_get("_thqa_str_entry_" + idx + "_offset"); e_reference = ctx_get("_thqa_str_entry_" + idx + "_ref"); seek(string_data_start + e_string_offset); str_value = cstring(); // Store values for child type ctx_set("_thqa_str_value", str_value); ctx_set("_thqa_str_id", e_string_id); ctx_set("_thqa_str_lang", e_lang); ctx_set("_thqa_str_ref", e_reference); // Create row via child type (fields become table columns) dummy_byte = bytesat(0, 1); entry_child = dummy_byte |> parse thqa_str_row; push("strings", entry_child); idx = idx + 1; } // Table display with columns matching child type field names // skip_tree() prevents tree children (table-only display) skip_tree("strings"); ui_table("strings", "Strings", "ID,Lang,Ref,Value"); seek(entries_end); srts_marker = ascii(read(4)) ui("String Marker"); u32 string_data_size ui("String Data Size"); total_strings = entry_count ui("Total Strings"); file_size = size() ui("File Size"); } // SpongeBob/Xbox-style string table (16-byte entries, UTF-16LE) type thqa_str_le ui("String Table", root) byteorder LE { criteria { require ascii(bytesat(0, 4)) == "bats"; } magic = ascii(read(4)) ui("Magic"); u32 version ui("Version"); u32 entry_count ui("Entry Count"); // Entries are 16 bytes each entries_end = 12 + (entry_count * 16); string_data_start = entries_end + 8; // First pass: collect all entry data idx = 0; repeat(entry_count) { u16 e_string_id; u16 e_type; u32 e_string_offset; u32 e_unknown; f32 e_float_val; ctx_set("_thqa_str_le_" + idx + "_id", e_string_id); ctx_set("_thqa_str_le_" + idx + "_type", e_type); ctx_set("_thqa_str_le_" + idx + "_offset", e_string_offset); ctx_set("_thqa_str_le_" + idx + "_float", e_float_val); idx = idx + 1; } // Skip srts marker and size skip(8); // Second pass: read UTF-16LE strings and create table rows idx = 0; repeat(entry_count) { e_string_id = ctx_get("_thqa_str_le_" + idx + "_id"); e_type = ctx_get("_thqa_str_le_" + idx + "_type"); e_string_offset = ctx_get("_thqa_str_le_" + idx + "_offset"); e_float_val = ctx_get("_thqa_str_le_" + idx + "_float"); seek(string_data_start + e_string_offset); str_value = wstring(); // Store values for child type ctx_set("_thqa_str_value", str_value); ctx_set("_thqa_str_id", e_string_id); ctx_set("_thqa_str_type", e_type); // Create row via child type (fields become table columns) dummy_byte = bytesat(0, 1); entry_child = dummy_byte |> parse thqa_str_le_row; push("strings", entry_child); idx = idx + 1; } // Table display with columns matching child type field names // skip_tree() prevents tree children (table-only display) skip_tree("strings"); ui_table("strings", "Strings", "ID,Type,Value"); seek(entries_end); srts_marker = ascii(read(4)) ui("String Marker"); u32 string_data_size ui("String Data Size"); total_strings = entry_count ui("Total Strings"); file_size = size() ui("File Size"); } // Row type for Avatar string table - field names match column names // set_hidden() prevents tree children while keeping table data type thqa_str_row ui("String") byteorder LE { set_hidden(); ID = ctx_get("_thqa_str_id"); Lang = ctx_get("_thqa_str_lang"); Ref = ctx_get("_thqa_str_ref"); // Replace Cyrillic button placeholders with readable Xbox button names Value = replace_xbox_buttons(ctx_get("_thqa_str_value")); } // Row type for SpongeBob string table - field names match column names type thqa_str_le_row ui("String") byteorder LE { set_hidden(); ID = ctx_get("_thqa_str_id"); Type = ctx_get("_thqa_str_type"); // Replace Cyrillic button placeholders with readable Xbox button names Value = replace_xbox_buttons(ctx_get("_thqa_str_value")); }