Decode infrastructure short trailing flag lane
This commit is contained in:
parent
1011f557e5
commit
9f43a27e07
3 changed files with 312 additions and 10 deletions
|
|
@ -1932,9 +1932,55 @@ pub struct SmpSavePlacedStructureDynamicSideBufferPayloadEnvelopeSummary {
|
||||||
pub dominant_profile_chunk_len: Option<usize>,
|
pub dominant_profile_chunk_len: Option<usize>,
|
||||||
pub dominant_profile_chunk_len_count: usize,
|
pub dominant_profile_chunk_len_count: usize,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
|
pub short_profile_flag_pair_summary:
|
||||||
|
Option<SmpSavePlacedStructureDynamicSideBufferShortProfileFlagPairSummary>,
|
||||||
|
#[serde(default)]
|
||||||
pub sample_rows: Vec<SmpSavePlacedStructureDynamicSideBufferPayloadEnvelopeSample>,
|
pub sample_rows: Vec<SmpSavePlacedStructureDynamicSideBufferPayloadEnvelopeSample>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
|
pub struct SmpSavePlacedStructureDynamicSideBufferShortProfileFlagPairSummary {
|
||||||
|
pub row_count_with_0x06_profile_span: usize,
|
||||||
|
pub unique_flag_pair_count: usize,
|
||||||
|
#[serde(default)]
|
||||||
|
pub dominant_first_flag_byte: Option<u8>,
|
||||||
|
#[serde(default)]
|
||||||
|
pub dominant_first_flag_byte_hex: Option<String>,
|
||||||
|
pub dominant_first_flag_byte_count: usize,
|
||||||
|
#[serde(default)]
|
||||||
|
pub dominant_second_flag_byte: Option<u8>,
|
||||||
|
#[serde(default)]
|
||||||
|
pub dominant_second_flag_byte_hex: Option<String>,
|
||||||
|
pub dominant_second_flag_byte_count: usize,
|
||||||
|
#[serde(default)]
|
||||||
|
pub dominant_flag_pair: Option<SmpSavePlacedStructureDynamicSideBufferShortProfileFlagPair>,
|
||||||
|
#[serde(default)]
|
||||||
|
pub sample_rows: Vec<SmpSavePlacedStructureDynamicSideBufferShortProfileFlagPairSample>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
|
pub struct SmpSavePlacedStructureDynamicSideBufferShortProfileFlagPair {
|
||||||
|
pub first_flag_byte: u8,
|
||||||
|
pub first_flag_byte_hex: String,
|
||||||
|
pub second_flag_byte: u8,
|
||||||
|
pub second_flag_byte_hex: String,
|
||||||
|
pub count: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
|
pub struct SmpSavePlacedStructureDynamicSideBufferShortProfileFlagPairSample {
|
||||||
|
pub sample_index: usize,
|
||||||
|
pub name_tag_relative_offset: usize,
|
||||||
|
#[serde(default)]
|
||||||
|
pub primary_name: Option<String>,
|
||||||
|
#[serde(default)]
|
||||||
|
pub secondary_name: Option<String>,
|
||||||
|
pub first_flag_byte: u8,
|
||||||
|
pub first_flag_byte_hex: String,
|
||||||
|
pub second_flag_byte: u8,
|
||||||
|
pub second_flag_byte_hex: String,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
pub struct SmpSavePlacedStructureDynamicSideBufferPayloadEnvelopeSample {
|
pub struct SmpSavePlacedStructureDynamicSideBufferPayloadEnvelopeSample {
|
||||||
pub sample_index: usize,
|
pub sample_index: usize,
|
||||||
|
|
@ -4035,6 +4081,33 @@ fn build_infrastructure_asset_trace_report(
|
||||||
.and_then(|summary| summary.dominant_profile_chunk_len)
|
.and_then(|summary| summary.dominant_profile_chunk_len)
|
||||||
.unwrap_or_default()
|
.unwrap_or_default()
|
||||||
),
|
),
|
||||||
|
"direct disassembly now also shows the post-+0x48 helper pair 0x52ebd0/0x52ec50 loading and serializing two single-byte lanes around the trailing 0x55f3 tag while folding them into bits 0x20 and 0x40 of [this+0x20]".to_string(),
|
||||||
|
format!(
|
||||||
|
"current save-side probe reports {} rows with the short 0x06-byte trailing span; dominant short flag pair is {}/{} x{}",
|
||||||
|
side_buffer
|
||||||
|
.and_then(|probe| probe.payload_envelope_summary.as_ref())
|
||||||
|
.and_then(|summary| summary.short_profile_flag_pair_summary.as_ref())
|
||||||
|
.map(|summary| summary.row_count_with_0x06_profile_span)
|
||||||
|
.unwrap_or_default(),
|
||||||
|
side_buffer
|
||||||
|
.and_then(|probe| probe.payload_envelope_summary.as_ref())
|
||||||
|
.and_then(|summary| summary.short_profile_flag_pair_summary.as_ref())
|
||||||
|
.and_then(|summary| summary.dominant_flag_pair.as_ref())
|
||||||
|
.map(|pair| pair.first_flag_byte_hex.as_str())
|
||||||
|
.unwrap_or("0x00"),
|
||||||
|
side_buffer
|
||||||
|
.and_then(|probe| probe.payload_envelope_summary.as_ref())
|
||||||
|
.and_then(|summary| summary.short_profile_flag_pair_summary.as_ref())
|
||||||
|
.and_then(|summary| summary.dominant_flag_pair.as_ref())
|
||||||
|
.map(|pair| pair.second_flag_byte_hex.as_str())
|
||||||
|
.unwrap_or("0x00"),
|
||||||
|
side_buffer
|
||||||
|
.and_then(|probe| probe.payload_envelope_summary.as_ref())
|
||||||
|
.and_then(|summary| summary.short_profile_flag_pair_summary.as_ref())
|
||||||
|
.and_then(|summary| summary.dominant_flag_pair.as_ref())
|
||||||
|
.map(|pair| pair.count)
|
||||||
|
.unwrap_or_default()
|
||||||
|
),
|
||||||
"local .rdata at 0x005cfd00 now also proves the infrastructure child table uses the shared tagged callback strip directly: slot +0x40 = 0x455fc0, slot +0x48 = 0x455870, and slot +0x4c = 0x455930".to_string(),
|
"local .rdata at 0x005cfd00 now also proves the infrastructure child table uses the shared tagged callback strip directly: slot +0x40 = 0x455fc0, slot +0x48 = 0x455870, and slot +0x4c = 0x455930".to_string(),
|
||||||
"direct disassembly now shows 0x0048a1e0 cloning the first child triplet bands through 0x52e880/0x52e720, destroying the prior child, seeding a new literal Infrastructure child through 0x455b70 with payload seed 0x5c87a8, attaching through 0x5395d0 or 0x53a5d0, and republishing the two bands through 0x52e8b0/0x530720".to_string(),
|
"direct disassembly now shows 0x0048a1e0 cloning the first child triplet bands through 0x52e880/0x52e720, destroying the prior child, seeding a new literal Infrastructure child through 0x455b70 with payload seed 0x5c87a8, attaching through 0x5395d0 or 0x53a5d0, and republishing the two bands through 0x52e8b0/0x530720".to_string(),
|
||||||
"direct disassembly now also shows the outer owner at 0x0048dcf0 reading a child count plus optional primary-child ordinal from the tagged stream through 0x531150, zeroing [this+0x08], dispatching each fresh child through 0x455a50 -> vtable slot +0x40, culling ordinals above 5, and restoring cached primary-child slot [this+0x248] from the saved ordinal".to_string(),
|
"direct disassembly now also shows the outer owner at 0x0048dcf0 reading a child count plus optional primary-child ordinal from the tagged stream through 0x531150, zeroing [this+0x08], dispatching each fresh child through 0x455a50 -> vtable slot +0x40, culling ordinals above 5, and restoring cached primary-child slot [this+0x248] from the saved ordinal".to_string(),
|
||||||
|
|
@ -4511,8 +4584,10 @@ pub fn load_save_slice_from_report(
|
||||||
if let Some(probe) = &placed_structure_dynamic_side_buffer_probe {
|
if let Some(probe) = &placed_structure_dynamic_side_buffer_probe {
|
||||||
let dominant_pattern = probe.compact_prefix_pattern_summaries.first();
|
let dominant_pattern = probe.compact_prefix_pattern_summaries.first();
|
||||||
let payload_envelope_summary = probe.payload_envelope_summary.as_ref();
|
let payload_envelope_summary = probe.payload_envelope_summary.as_ref();
|
||||||
|
let short_profile_flag_pair_summary = payload_envelope_summary
|
||||||
|
.and_then(|summary| summary.short_profile_flag_pair_summary.as_ref());
|
||||||
notes.push(format!(
|
notes.push(format!(
|
||||||
"Raw save also exposes the separate placed-structure dynamic-side-buffer candidate 0x38a5/0x38a6/0x38a7: live_record_count={}, owner-shared 0x38a6 dword={} at relative offset 0x{:x}, first compact prefix=({},{},{}), first embedded names={:?}/{:?}/{:?}, embedded 0x55f1 row count={}, rows with tertiary 0x55f1 string={}, unique compact prefix patterns={}, 0x55f3-leading rows={}, complete 0x55f1/0x55f2/0x55f3 envelopes={}, dominant 0x55f2 chunk len=0x{:x} x{}, dominant 0x55f3 span=0x{:x} x{}, dominant compact pattern={}/{}/{} x{}.",
|
"Raw save also exposes the separate placed-structure dynamic-side-buffer candidate 0x38a5/0x38a6/0x38a7: live_record_count={}, owner-shared 0x38a6 dword={} at relative offset 0x{:x}, first compact prefix=({},{},{}), first embedded names={:?}/{:?}/{:?}, embedded 0x55f1 row count={}, rows with tertiary 0x55f1 string={}, unique compact prefix patterns={}, 0x55f3-leading rows={}, complete 0x55f1/0x55f2/0x55f3 envelopes={}, dominant 0x55f2 chunk len=0x{:x} x{}, dominant 0x55f3 span=0x{:x} x{}, dominant short 0x55f3 flag pair={}/{} x{}, dominant compact pattern={}/{}/{} x{}.",
|
||||||
probe.live_record_count,
|
probe.live_record_count,
|
||||||
probe.owner_shared_dword_hex,
|
probe.owner_shared_dword_hex,
|
||||||
probe.owner_shared_dword_relative_offset,
|
probe.owner_shared_dword_relative_offset,
|
||||||
|
|
@ -4541,6 +4616,18 @@ pub fn load_save_slice_from_report(
|
||||||
payload_envelope_summary
|
payload_envelope_summary
|
||||||
.map(|summary| summary.dominant_profile_chunk_len_count)
|
.map(|summary| summary.dominant_profile_chunk_len_count)
|
||||||
.unwrap_or_default(),
|
.unwrap_or_default(),
|
||||||
|
short_profile_flag_pair_summary
|
||||||
|
.and_then(|summary| summary.dominant_flag_pair.as_ref())
|
||||||
|
.map(|pair| pair.first_flag_byte_hex.as_str())
|
||||||
|
.unwrap_or("0x00"),
|
||||||
|
short_profile_flag_pair_summary
|
||||||
|
.and_then(|summary| summary.dominant_flag_pair.as_ref())
|
||||||
|
.map(|pair| pair.second_flag_byte_hex.as_str())
|
||||||
|
.unwrap_or("0x00"),
|
||||||
|
short_profile_flag_pair_summary
|
||||||
|
.and_then(|summary| summary.dominant_flag_pair.as_ref())
|
||||||
|
.map(|pair| pair.count)
|
||||||
|
.unwrap_or_default(),
|
||||||
dominant_pattern
|
dominant_pattern
|
||||||
.map(|pattern| pattern.prefix_leading_dword_hex.as_str())
|
.map(|pattern| pattern.prefix_leading_dword_hex.as_str())
|
||||||
.unwrap_or("0x00000000"),
|
.unwrap_or("0x00000000"),
|
||||||
|
|
@ -5025,8 +5112,10 @@ pub fn inspect_save_company_and_chairman_analysis_bytes(
|
||||||
if let Some(side_buffer) = placed_structure_dynamic_side_buffer.as_ref() {
|
if let Some(side_buffer) = placed_structure_dynamic_side_buffer.as_ref() {
|
||||||
let dominant_pattern = side_buffer.compact_prefix_pattern_summaries.first();
|
let dominant_pattern = side_buffer.compact_prefix_pattern_summaries.first();
|
||||||
let payload_envelope_summary = side_buffer.payload_envelope_summary.as_ref();
|
let payload_envelope_summary = side_buffer.payload_envelope_summary.as_ref();
|
||||||
|
let short_profile_flag_pair_summary = payload_envelope_summary
|
||||||
|
.and_then(|summary| summary.short_profile_flag_pair_summary.as_ref());
|
||||||
notes.push(format!(
|
notes.push(format!(
|
||||||
"Placed-structure analysis now also exports the separate 0x38a5 dynamic side-buffer owner seam with {} embedded name rows, {} decoded rows across {} unique name pairs, {} rows with a tertiary 0x55f1 string, {} unique compact prefix patterns, {} rows whose leading dword matches 0x55f3, {} complete 0x55f1/0x55f2/0x55f3 envelopes, dominant 0x55f2 chunk len=0x{:x} x{}, dominant 0x55f3 span=0x{:x} x{}, and dominant compact pattern={}/{}/{} x{}.",
|
"Placed-structure analysis now also exports the separate 0x38a5 dynamic side-buffer owner seam with {} embedded name rows, {} decoded rows across {} unique name pairs, {} rows with a tertiary 0x55f1 string, {} unique compact prefix patterns, {} rows whose leading dword matches 0x55f3, {} complete 0x55f1/0x55f2/0x55f3 envelopes, dominant 0x55f2 chunk len=0x{:x} x{}, dominant 0x55f3 span=0x{:x} x{}, dominant short 0x55f3 flag pair={}/{} x{}, and dominant compact pattern={}/{}/{} x{}.",
|
||||||
side_buffer.embedded_name_tag_count,
|
side_buffer.embedded_name_tag_count,
|
||||||
side_buffer.decoded_embedded_name_row_count,
|
side_buffer.decoded_embedded_name_row_count,
|
||||||
side_buffer.unique_embedded_name_pair_count,
|
side_buffer.unique_embedded_name_pair_count,
|
||||||
|
|
@ -5048,6 +5137,18 @@ pub fn inspect_save_company_and_chairman_analysis_bytes(
|
||||||
payload_envelope_summary
|
payload_envelope_summary
|
||||||
.map(|summary| summary.dominant_profile_chunk_len_count)
|
.map(|summary| summary.dominant_profile_chunk_len_count)
|
||||||
.unwrap_or_default(),
|
.unwrap_or_default(),
|
||||||
|
short_profile_flag_pair_summary
|
||||||
|
.and_then(|summary| summary.dominant_flag_pair.as_ref())
|
||||||
|
.map(|pair| pair.first_flag_byte_hex.as_str())
|
||||||
|
.unwrap_or("0x00"),
|
||||||
|
short_profile_flag_pair_summary
|
||||||
|
.and_then(|summary| summary.dominant_flag_pair.as_ref())
|
||||||
|
.map(|pair| pair.second_flag_byte_hex.as_str())
|
||||||
|
.unwrap_or("0x00"),
|
||||||
|
short_profile_flag_pair_summary
|
||||||
|
.and_then(|summary| summary.dominant_flag_pair.as_ref())
|
||||||
|
.map(|pair| pair.count)
|
||||||
|
.unwrap_or_default(),
|
||||||
dominant_pattern
|
dominant_pattern
|
||||||
.map(|pattern| pattern.prefix_leading_dword_hex.as_str())
|
.map(|pattern| pattern.prefix_leading_dword_hex.as_str())
|
||||||
.unwrap_or("0x00000000"),
|
.unwrap_or("0x00000000"),
|
||||||
|
|
@ -11833,6 +11934,8 @@ fn parse_save_placed_structure_dynamic_side_buffer_probe(
|
||||||
prefix_leading_dword: u32,
|
prefix_leading_dword: u32,
|
||||||
prefix_trailing_word: u16,
|
prefix_trailing_word: u16,
|
||||||
prefix_separator_byte: u8,
|
prefix_separator_byte: u8,
|
||||||
|
name_payload_relative_offset: usize,
|
||||||
|
name_payload_len: usize,
|
||||||
primary_name: Option<String>,
|
primary_name: Option<String>,
|
||||||
secondary_name: Option<String>,
|
secondary_name: Option<String>,
|
||||||
tertiary_name: Option<String>,
|
tertiary_name: Option<String>,
|
||||||
|
|
@ -11868,6 +11971,8 @@ fn parse_save_placed_structure_dynamic_side_buffer_probe(
|
||||||
name_to_policy_gap_len: Option<usize>,
|
name_to_policy_gap_len: Option<usize>,
|
||||||
policy_chunk_len: Option<usize>,
|
policy_chunk_len: Option<usize>,
|
||||||
profile_chunk_len_to_next_name_or_end: Option<usize>,
|
profile_chunk_len_to_next_name_or_end: Option<usize>,
|
||||||
|
short_profile_first_flag_byte: Option<u8>,
|
||||||
|
short_profile_second_flag_byte: Option<u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
if file_extension_hint != Some("gms") {
|
if file_extension_hint != Some("gms") {
|
||||||
|
|
@ -12007,18 +12112,23 @@ fn parse_save_placed_structure_dynamic_side_buffer_probe(
|
||||||
else {
|
else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
if let Some(names) = parse_save_len_prefixed_ascii_name_triplet(name_payload) {
|
if let Some((names, name_payload_len)) =
|
||||||
parsed_names = Some(names);
|
parse_save_len_prefixed_ascii_name_triplet_and_consumed_len(name_payload)
|
||||||
|
{
|
||||||
|
parsed_names = Some((relative_name_offset, name_payload_len, names));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let (primary_name, secondary_name, tertiary_name) =
|
let (name_payload_relative_offset, name_payload_len, names) =
|
||||||
parsed_names.unwrap_or_default();
|
parsed_names.unwrap_or((4usize, 0usize, Default::default()));
|
||||||
|
let (primary_name, secondary_name, tertiary_name) = names;
|
||||||
Some(EmbeddedNameRow {
|
Some(EmbeddedNameRow {
|
||||||
name_tag_relative_offset,
|
name_tag_relative_offset,
|
||||||
prefix_leading_dword,
|
prefix_leading_dword,
|
||||||
prefix_trailing_word,
|
prefix_trailing_word,
|
||||||
prefix_separator_byte,
|
prefix_separator_byte,
|
||||||
|
name_payload_relative_offset,
|
||||||
|
name_payload_len,
|
||||||
primary_name: (!primary_name.is_empty()).then_some(primary_name),
|
primary_name: (!primary_name.is_empty()).then_some(primary_name),
|
||||||
secondary_name: (!secondary_name.is_empty()).then_some(secondary_name),
|
secondary_name: (!secondary_name.is_empty()).then_some(secondary_name),
|
||||||
tertiary_name,
|
tertiary_name,
|
||||||
|
|
@ -12037,10 +12147,11 @@ fn parse_save_placed_structure_dynamic_side_buffer_probe(
|
||||||
.get(row_index + 1)
|
.get(row_index + 1)
|
||||||
.copied()
|
.copied()
|
||||||
.or(Some(records_payload.len()));
|
.or(Some(records_payload.len()));
|
||||||
let name_payload_end_relative_offset = records_payload
|
let name_payload_end_relative_offset = Some(
|
||||||
.get(row.name_tag_relative_offset + 4..)
|
row.name_tag_relative_offset
|
||||||
.and_then(parse_save_len_prefixed_ascii_name_triplet_and_consumed_len)
|
+ row.name_payload_relative_offset
|
||||||
.map(|(_, consumed_len)| row.name_tag_relative_offset + 4 + consumed_len);
|
+ row.name_payload_len,
|
||||||
|
);
|
||||||
let policy_tag_relative_offset =
|
let policy_tag_relative_offset =
|
||||||
policy_tag_offsets.iter().copied().find(|offset| {
|
policy_tag_offsets.iter().copied().find(|offset| {
|
||||||
*offset > row.name_tag_relative_offset
|
*offset > row.name_tag_relative_offset
|
||||||
|
|
@ -12075,6 +12186,18 @@ fn parse_save_placed_structure_dynamic_side_buffer_probe(
|
||||||
.checked_sub(profile_tag_relative_offset + 4)
|
.checked_sub(profile_tag_relative_offset + 4)
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
let short_profile_first_flag_byte =
|
||||||
|
profile_tag_relative_offset.and_then(|profile_tag_relative_offset| {
|
||||||
|
records_payload
|
||||||
|
.get(profile_tag_relative_offset + 4)
|
||||||
|
.copied()
|
||||||
|
});
|
||||||
|
let short_profile_second_flag_byte =
|
||||||
|
profile_tag_relative_offset.and_then(|profile_tag_relative_offset| {
|
||||||
|
records_payload
|
||||||
|
.get(profile_tag_relative_offset + 5)
|
||||||
|
.copied()
|
||||||
|
});
|
||||||
PayloadEnvelopeRow {
|
PayloadEnvelopeRow {
|
||||||
name_tag_relative_offset: row.name_tag_relative_offset,
|
name_tag_relative_offset: row.name_tag_relative_offset,
|
||||||
primary_name: row.primary_name.clone(),
|
primary_name: row.primary_name.clone(),
|
||||||
|
|
@ -12086,6 +12209,8 @@ fn parse_save_placed_structure_dynamic_side_buffer_probe(
|
||||||
name_to_policy_gap_len,
|
name_to_policy_gap_len,
|
||||||
policy_chunk_len,
|
policy_chunk_len,
|
||||||
profile_chunk_len_to_next_name_or_end,
|
profile_chunk_len_to_next_name_or_end,
|
||||||
|
short_profile_first_flag_byte,
|
||||||
|
short_profile_second_flag_byte,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
@ -12305,6 +12430,112 @@ fn parse_save_placed_structure_dynamic_side_buffer_probe(
|
||||||
.then_with(|| right_len.cmp(left_len))
|
.then_with(|| right_len.cmp(left_len))
|
||||||
})
|
})
|
||||||
.map(|(len, count)| (*len, *count));
|
.map(|(len, count)| (*len, *count));
|
||||||
|
let short_profile_flag_rows = payload_envelope_rows
|
||||||
|
.iter()
|
||||||
|
.filter(|row| row.profile_chunk_len_to_next_name_or_end == Some(6))
|
||||||
|
.filter_map(|row| {
|
||||||
|
Some((
|
||||||
|
row.name_tag_relative_offset,
|
||||||
|
row.primary_name.clone(),
|
||||||
|
row.secondary_name.clone(),
|
||||||
|
row.short_profile_first_flag_byte?,
|
||||||
|
row.short_profile_second_flag_byte?,
|
||||||
|
))
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
let mut short_profile_flag_pair_counts = BTreeMap::<(u8, u8), usize>::new();
|
||||||
|
let mut short_profile_first_flag_counts = BTreeMap::<u8, usize>::new();
|
||||||
|
let mut short_profile_second_flag_counts = BTreeMap::<u8, usize>::new();
|
||||||
|
for (_, _, _, first_flag_byte, second_flag_byte) in &short_profile_flag_rows {
|
||||||
|
*short_profile_flag_pair_counts
|
||||||
|
.entry((*first_flag_byte, *second_flag_byte))
|
||||||
|
.or_default() += 1;
|
||||||
|
*short_profile_first_flag_counts
|
||||||
|
.entry(*first_flag_byte)
|
||||||
|
.or_default() += 1;
|
||||||
|
*short_profile_second_flag_counts
|
||||||
|
.entry(*second_flag_byte)
|
||||||
|
.or_default() += 1;
|
||||||
|
}
|
||||||
|
let dominant_short_profile_flag_pair = short_profile_flag_pair_counts
|
||||||
|
.iter()
|
||||||
|
.max_by(|(left_pair, left_count), (right_pair, right_count)| {
|
||||||
|
left_count
|
||||||
|
.cmp(right_count)
|
||||||
|
.then_with(|| right_pair.cmp(left_pair))
|
||||||
|
})
|
||||||
|
.map(|((first_flag_byte, second_flag_byte), count)| {
|
||||||
|
SmpSavePlacedStructureDynamicSideBufferShortProfileFlagPair {
|
||||||
|
first_flag_byte: *first_flag_byte,
|
||||||
|
first_flag_byte_hex: format!("0x{first_flag_byte:02x}"),
|
||||||
|
second_flag_byte: *second_flag_byte,
|
||||||
|
second_flag_byte_hex: format!("0x{second_flag_byte:02x}"),
|
||||||
|
count: *count,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
let dominant_short_profile_first_flag = short_profile_first_flag_counts
|
||||||
|
.iter()
|
||||||
|
.max_by(|(left_byte, left_count), (right_byte, right_count)| {
|
||||||
|
left_count
|
||||||
|
.cmp(right_count)
|
||||||
|
.then_with(|| right_byte.cmp(left_byte))
|
||||||
|
})
|
||||||
|
.map(|(byte, count)| (*byte, *count));
|
||||||
|
let dominant_short_profile_second_flag = short_profile_second_flag_counts
|
||||||
|
.iter()
|
||||||
|
.max_by(|(left_byte, left_count), (right_byte, right_count)| {
|
||||||
|
left_count
|
||||||
|
.cmp(right_count)
|
||||||
|
.then_with(|| right_byte.cmp(left_byte))
|
||||||
|
})
|
||||||
|
.map(|(byte, count)| (*byte, *count));
|
||||||
|
let short_profile_flag_pair_summary = Some(
|
||||||
|
SmpSavePlacedStructureDynamicSideBufferShortProfileFlagPairSummary {
|
||||||
|
row_count_with_0x06_profile_span: short_profile_flag_rows.len(),
|
||||||
|
unique_flag_pair_count: short_profile_flag_pair_counts.len(),
|
||||||
|
dominant_first_flag_byte: dominant_short_profile_first_flag.map(|(byte, _)| byte),
|
||||||
|
dominant_first_flag_byte_hex: dominant_short_profile_first_flag
|
||||||
|
.map(|(byte, _)| format!("0x{byte:02x}")),
|
||||||
|
dominant_first_flag_byte_count: dominant_short_profile_first_flag
|
||||||
|
.map(|(_, count)| count)
|
||||||
|
.unwrap_or_default(),
|
||||||
|
dominant_second_flag_byte: dominant_short_profile_second_flag.map(|(byte, _)| byte),
|
||||||
|
dominant_second_flag_byte_hex: dominant_short_profile_second_flag
|
||||||
|
.map(|(byte, _)| format!("0x{byte:02x}")),
|
||||||
|
dominant_second_flag_byte_count: dominant_short_profile_second_flag
|
||||||
|
.map(|(_, count)| count)
|
||||||
|
.unwrap_or_default(),
|
||||||
|
dominant_flag_pair: dominant_short_profile_flag_pair,
|
||||||
|
sample_rows: short_profile_flag_rows
|
||||||
|
.iter()
|
||||||
|
.take(8)
|
||||||
|
.enumerate()
|
||||||
|
.map(
|
||||||
|
|(
|
||||||
|
sample_index,
|
||||||
|
(
|
||||||
|
name_tag_relative_offset,
|
||||||
|
primary_name,
|
||||||
|
secondary_name,
|
||||||
|
first_flag_byte,
|
||||||
|
second_flag_byte,
|
||||||
|
),
|
||||||
|
)| {
|
||||||
|
SmpSavePlacedStructureDynamicSideBufferShortProfileFlagPairSample {
|
||||||
|
sample_index,
|
||||||
|
name_tag_relative_offset: *name_tag_relative_offset,
|
||||||
|
primary_name: primary_name.clone(),
|
||||||
|
secondary_name: secondary_name.clone(),
|
||||||
|
first_flag_byte: *first_flag_byte,
|
||||||
|
first_flag_byte_hex: format!("0x{first_flag_byte:02x}"),
|
||||||
|
second_flag_byte: *second_flag_byte,
|
||||||
|
second_flag_byte_hex: format!("0x{second_flag_byte:02x}"),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.collect(),
|
||||||
|
},
|
||||||
|
);
|
||||||
let payload_envelope_summary = Some(
|
let payload_envelope_summary = Some(
|
||||||
SmpSavePlacedStructureDynamicSideBufferPayloadEnvelopeSummary {
|
SmpSavePlacedStructureDynamicSideBufferPayloadEnvelopeSummary {
|
||||||
row_count_with_policy_tag_before_next_name,
|
row_count_with_policy_tag_before_next_name,
|
||||||
|
|
@ -12321,6 +12552,7 @@ fn parse_save_placed_structure_dynamic_side_buffer_probe(
|
||||||
dominant_profile_chunk_len_count: dominant_profile_chunk_len
|
dominant_profile_chunk_len_count: dominant_profile_chunk_len
|
||||||
.map(|(_, count)| count)
|
.map(|(_, count)| count)
|
||||||
.unwrap_or_default(),
|
.unwrap_or_default(),
|
||||||
|
short_profile_flag_pair_summary: short_profile_flag_pair_summary.clone(),
|
||||||
sample_rows: payload_envelope_rows
|
sample_rows: payload_envelope_rows
|
||||||
.iter()
|
.iter()
|
||||||
.take(8)
|
.take(8)
|
||||||
|
|
@ -12450,6 +12682,24 @@ fn parse_save_placed_structure_dynamic_side_buffer_probe(
|
||||||
"no dominant embedded 0x55f3 payload-to-next-name span was available"
|
"no dominant embedded 0x55f3 payload-to-next-name span was available"
|
||||||
.to_string()
|
.to_string()
|
||||||
}),
|
}),
|
||||||
|
short_profile_flag_pair_summary
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|summary| summary.dominant_flag_pair.as_ref())
|
||||||
|
.map(|pair| {
|
||||||
|
format!(
|
||||||
|
"direct disassembly now bounds the short trailing lane through 0x52ebd0/0x52ec50 as two serialized flag bytes folded into [this+0x20] bits 0x20/0x40; grounded 0x06-byte rows currently favor {}/{} across {} rows ({} rows total with the short span)",
|
||||||
|
pair.first_flag_byte_hex,
|
||||||
|
pair.second_flag_byte_hex,
|
||||||
|
pair.count,
|
||||||
|
short_profile_flag_pair_summary
|
||||||
|
.as_ref()
|
||||||
|
.map(|summary| summary.row_count_with_0x06_profile_span)
|
||||||
|
.unwrap_or_default()
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.unwrap_or_else(|| {
|
||||||
|
"no dominant short trailing flag-byte pair was available".to_string()
|
||||||
|
}),
|
||||||
dominant_compact_prefix_pattern
|
dominant_compact_prefix_pattern
|
||||||
.map(|pattern| {
|
.map(|pattern| {
|
||||||
format!(
|
format!(
|
||||||
|
|
@ -22489,6 +22739,28 @@ mod tests {
|
||||||
dominant_policy_chunk_len_count: 110,
|
dominant_policy_chunk_len_count: 110,
|
||||||
dominant_profile_chunk_len: Some(0x08),
|
dominant_profile_chunk_len: Some(0x08),
|
||||||
dominant_profile_chunk_len_count: 90,
|
dominant_profile_chunk_len_count: 90,
|
||||||
|
short_profile_flag_pair_summary: Some(
|
||||||
|
SmpSavePlacedStructureDynamicSideBufferShortProfileFlagPairSummary {
|
||||||
|
row_count_with_0x06_profile_span: 72,
|
||||||
|
unique_flag_pair_count: 2,
|
||||||
|
dominant_first_flag_byte: Some(0x01),
|
||||||
|
dominant_first_flag_byte_hex: Some("0x01".to_string()),
|
||||||
|
dominant_first_flag_byte_count: 60,
|
||||||
|
dominant_second_flag_byte: Some(0x00),
|
||||||
|
dominant_second_flag_byte_hex: Some("0x00".to_string()),
|
||||||
|
dominant_second_flag_byte_count: 55,
|
||||||
|
dominant_flag_pair: Some(
|
||||||
|
SmpSavePlacedStructureDynamicSideBufferShortProfileFlagPair {
|
||||||
|
first_flag_byte: 0x01,
|
||||||
|
first_flag_byte_hex: "0x01".to_string(),
|
||||||
|
second_flag_byte: 0x00,
|
||||||
|
second_flag_byte_hex: "0x00".to_string(),
|
||||||
|
count: 48,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
sample_rows: Vec::new(),
|
||||||
|
},
|
||||||
|
),
|
||||||
sample_rows: Vec::new(),
|
sample_rows: Vec::new(),
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
@ -22542,6 +22814,15 @@ mod tests {
|
||||||
.any(|line| line.contains("0x005181f0/0x00518260")
|
.any(|line| line.contains("0x005181f0/0x00518260")
|
||||||
&& line.contains("previous live id"))
|
&& line.contains("previous live id"))
|
||||||
);
|
);
|
||||||
|
assert!(
|
||||||
|
trace.candidate_consumer_hypotheses[0]
|
||||||
|
.evidence
|
||||||
|
.iter()
|
||||||
|
.any(|line| {
|
||||||
|
line.contains("0x52ebd0/0x52ec50")
|
||||||
|
&& (line.contains("bits 0x20/0x40") || line.contains("bits 0x20 and 0x40"))
|
||||||
|
})
|
||||||
|
);
|
||||||
assert_eq!(trace.branches[0].status, "grounded_separate_owner_seam");
|
assert_eq!(trace.branches[0].status, "grounded_separate_owner_seam");
|
||||||
assert_eq!(trace.branches[1].status, "disproved_by_grounded_probe");
|
assert_eq!(trace.branches[1].status, "disproved_by_grounded_probe");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2943,6 +2943,15 @@ The low helper strip beneath that shared family is tighter now too: `0x0052ecd0`
|
||||||
to the first string when absent. So the remaining payload question is no longer “where is the
|
to the first string when absent. So the remaining payload question is no longer “where is the
|
||||||
third string hiding?”; it is how the current dual-name save-side rows align with the full
|
third string hiding?”; it is how the current dual-name save-side rows align with the full
|
||||||
payload-stream grouping and the later tagged value roles.
|
payload-stream grouping and the later tagged value roles.
|
||||||
|
That trailing-value strip is tighter now too: direct disassembly of the post-`+0x48` helper pair
|
||||||
|
`0x0052ebd0/0x0052ec50` shows two serialized single-byte lanes folded into bits `0x20` and
|
||||||
|
`0x40` of `[this+0x20]`. Grounded `q.gms` side-buffer probes now show that all embedded rows sit
|
||||||
|
inside complete `0x55f1 -> 0x55f2 -> 0x55f3` envelopes, every embedded `0x55f2` chunk is the
|
||||||
|
fixed `0x1a` bytes that `0x00455870` expects, and the dominant short trailing `0x55f3` span is
|
||||||
|
the `0x06`-byte form with flag pair `0x00/0x00` across `72` rows. So the next remaining
|
||||||
|
infrastructure question is no longer whether a short trailing lane exists; it is how those
|
||||||
|
compact-prefix regimes and short flag-byte pairs feed the child-count / primary-child restore
|
||||||
|
state above `0x0048dcf0`.
|
||||||
The child loader family is explicit now too: local `.rdata` at `0x005cfd00` proves the
|
The child loader family is explicit now too: local `.rdata` at `0x005cfd00` proves the
|
||||||
`Infrastructure` child vtable uses the shared tagged callback strip directly, with
|
`Infrastructure` child vtable uses the shared tagged callback strip directly, with
|
||||||
`+0x40 = 0x00455fc0`, `+0x48 = 0x00455870`, and `+0x4c = 0x00455930`. So the remaining
|
`+0x40 = 0x00455fc0`, `+0x48 = 0x00455870`, and `+0x4c = 0x00455930`. So the remaining
|
||||||
|
|
|
||||||
|
|
@ -95,6 +95,13 @@ Working rule:
|
||||||
infrastructure pass should stop asking whether the shared tagged callback sequence is present at
|
infrastructure pass should stop asking whether the shared tagged callback sequence is present at
|
||||||
all and instead decode the short `0x55f3` payload role and its relation to the compact-prefix
|
all and instead decode the short `0x55f3` payload role and its relation to the compact-prefix
|
||||||
regimes and primary-child restore path.
|
regimes and primary-child restore path.
|
||||||
|
- That short trailing lane is tighter now too: direct disassembly of `0x0052ebd0/0x0052ec50`
|
||||||
|
shows the post-`+0x48` helper pair loading and serializing two single-byte lanes that fold into
|
||||||
|
bits `0x20` and `0x40` of `[this+0x20]`, and the save-side probe now shows the dominant
|
||||||
|
`0x06`-byte rows all carrying the same grounded flag pair `0x00/0x00` on `q.gms`. So the next
|
||||||
|
concrete infrastructure question is no longer “is there a short trailing flag lane?”; it is how
|
||||||
|
the compact-prefix regimes and those flag-byte pairs feed the child-count / primary-child restore
|
||||||
|
state above `0x0048dcf0`.
|
||||||
- Reconstruct the save-side region record body on top of the newly corrected non-direct tagged
|
- Reconstruct the save-side region record body on top of the newly corrected non-direct tagged
|
||||||
region seam (`0x5209/0x520a/0x520b`, stride hint `0x06`, `Marker09` record stems) now that the
|
region seam (`0x5209/0x520a/0x520b`, stride hint `0x06`, `Marker09` record stems) now that the
|
||||||
`0x55f3` payload is known to be fully consumed by the embedded profile collection on grounded
|
`0x55f3` payload is known to be fully consumed by the embedded profile collection on grounded
|
||||||
|
|
@ -227,6 +234,11 @@ Working rule:
|
||||||
and sampled row boundaries. That means the next pass can decode the short embedded `0x55f3`
|
and sampled row boundaries. That means the next pass can decode the short embedded `0x55f3`
|
||||||
payload lane on top of already grounded row boundaries instead of rediscovering the same
|
payload lane on top of already grounded row boundaries instead of rediscovering the same
|
||||||
envelopes again.
|
envelopes again.
|
||||||
|
- That same probe now also exports the grounded short trailing flag-byte pair summary for the
|
||||||
|
dominant `0x06`-byte rows, while the infrastructure trace carries the matching
|
||||||
|
`0x0052ebd0/0x0052ec50` helper seam. That means the next pass can aim directly at how those
|
||||||
|
flags combine with compact-prefix regimes and primary-child restore state instead of treating the
|
||||||
|
short lane as anonymous payload.
|
||||||
- That same trace now also ranks those consumers into explicit hypotheses, so the next
|
- That same trace now also ranks those consumers into explicit hypotheses, so the next
|
||||||
infrastructure pass should start with the attach/rebuild strip instead of treating all
|
infrastructure pass should start with the attach/rebuild strip instead of treating all
|
||||||
candidate owners as equally likely.
|
candidate owners as equally likely.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue