Expose building source selector bytes
This commit is contained in:
parent
03fdcdf998
commit
f690a1ebd0
3 changed files with 133 additions and 19 deletions
|
|
@ -156,25 +156,26 @@ rebuild a substantial portion of each live candidate record:
|
||||||
`[candidate+0x79c/+0x7a0/+0x78c/+0x790/+0x794/+0x7b0]`
|
`[candidate+0x79c/+0x7a0/+0x78c/+0x790/+0x794/+0x7b0]`
|
||||||
- reads the fixed per-record stream fields at
|
- reads the fixed per-record stream fields at
|
||||||
`[candidate+0x04/+0x22/+0x26/+0x28/+0x2a/+0x2e/+0x32/+0x33]`
|
`[candidate+0x04/+0x22/+0x26/+0x28/+0x2a/+0x2e/+0x32/+0x33]`
|
||||||
|
- restores the selector-bank bytes
|
||||||
|
`[candidate+0xb9/+0xba/+0xbb]`
|
||||||
- allocates and streams the packed `0xbc` descriptor array into `[candidate+0x37]`
|
- allocates and streams the packed `0xbc` descriptor array into `[candidate+0x37]`
|
||||||
|
|
||||||
But in the checked `0x004120b0` body there is still **no** write to:
|
|
||||||
|
|
||||||
- `[candidate+0xba]`
|
|
||||||
- `[candidate+0xbb]`
|
|
||||||
|
|
||||||
So the current strongest ownership split is now:
|
So the current strongest ownership split is now:
|
||||||
|
|
||||||
- direct named-availability table `[state+0x66b2]` is not the missing differentiator by itself
|
- direct named-availability table `[state+0x66b2]` is not the missing differentiator by itself
|
||||||
- per-record stream-load `0x004120b0` is also not where the port-versus-warehouse availability
|
- both source-record import `0x00414490` and per-record stream-load `0x004120b0` do carry the
|
||||||
bytes are authored
|
relevant selector-bank bytes from persisted/source state into the live candidate family
|
||||||
- the surviving writer-side frontier is the later template-bank path in `0x00412d70`, where the
|
- but the stock `Data/BuildingTypes/*.bca` corpus currently keeps `[record+0xb8/+0xb9/+0xba/+0xbb]`
|
||||||
imported record is cloned or reused against one bank-qualified live candidate before the runtime
|
at zero across every observed file, including `Warehouse.bca` and `Port.bca`
|
||||||
descriptor and membership rebuilds run
|
- so the surviving frontier is no longer “does the lower loader import `[candidate+0xba/+0xbb]`?”
|
||||||
|
but rather which later owner or alternate content path makes the live bank-qualified split differ
|
||||||
|
from that all-zero shipped BCA corpus before `0x00412d70` clones or reuses one bank-qualified
|
||||||
|
live candidate
|
||||||
|
|
||||||
That makes the next Tier 2 question more concrete still:
|
That makes the next Tier 2 question more concrete still:
|
||||||
|
|
||||||
- how the bank-qualified template source selected under `[candidate+0xba]` versus `[candidate+0xbb]`
|
- how any nonzero bank-qualified template source under `[candidate+0xba]` versus `[candidate+0xbb]`
|
||||||
seeds the later `Warehouse%02d` side in `Louisiana.gmp`
|
is actually seeded above the stock all-zero BCA corpus, and then
|
||||||
|
drives the later `Warehouse%02d` side in `Louisiana.gmp`
|
||||||
- and whether that preserved bank/template state is the real bridge from the minimal recipe cluster
|
- and whether that preserved bank/template state is the real bridge from the minimal recipe cluster
|
||||||
to the shipped `5200 :: [7:0]` `Add Building Warehouse05` row
|
to the shipped `5200 :: [7:0]` `Add Building Warehouse05` row
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,10 @@ pub struct BuildingTypeSourceFile {
|
||||||
pub raw_stem: String,
|
pub raw_stem: String,
|
||||||
pub canonical_stem: String,
|
pub canonical_stem: String,
|
||||||
pub source_kind: BuildingTypeSourceKind,
|
pub source_kind: BuildingTypeSourceKind,
|
||||||
|
#[serde(default)]
|
||||||
|
pub byte_len: Option<usize>,
|
||||||
|
#[serde(default)]
|
||||||
|
pub bca_selector_probe: Option<BuildingTypeBcaSelectorProbe>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
|
|
@ -27,6 +31,29 @@ pub struct BuildingTypeSourceEntry {
|
||||||
pub file_names: Vec<String>,
|
pub file_names: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
|
pub struct BuildingTypeBcaSelectorProbe {
|
||||||
|
pub byte_0xb8: u8,
|
||||||
|
pub byte_0xb8_hex: String,
|
||||||
|
pub byte_0xb9: u8,
|
||||||
|
pub byte_0xb9_hex: String,
|
||||||
|
pub byte_0xba: u8,
|
||||||
|
pub byte_0xba_hex: String,
|
||||||
|
pub byte_0xbb: u8,
|
||||||
|
pub byte_0xbb_hex: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
|
pub struct BuildingTypeBcaSelectorPatternSummary {
|
||||||
|
pub byte_len: usize,
|
||||||
|
pub byte_0xb8_hex: String,
|
||||||
|
pub byte_0xb9_hex: String,
|
||||||
|
pub byte_0xba_hex: String,
|
||||||
|
pub byte_0xbb_hex: String,
|
||||||
|
pub file_count: usize,
|
||||||
|
pub sample_file_names: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
pub struct BuildingTypeNamedBindingComparison {
|
pub struct BuildingTypeNamedBindingComparison {
|
||||||
pub bindings_path: String,
|
pub bindings_path: String,
|
||||||
|
|
@ -42,9 +69,11 @@ pub struct BuildingTypeSourceReport {
|
||||||
pub bca_file_count: usize,
|
pub bca_file_count: usize,
|
||||||
pub bty_file_count: usize,
|
pub bty_file_count: usize,
|
||||||
pub unique_canonical_stem_count: usize,
|
pub unique_canonical_stem_count: usize,
|
||||||
|
pub bca_selector_pattern_count: usize,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub named_binding_comparison: Option<BuildingTypeNamedBindingComparison>,
|
pub named_binding_comparison: Option<BuildingTypeNamedBindingComparison>,
|
||||||
pub notes: Vec<String>,
|
pub notes: Vec<String>,
|
||||||
|
pub bca_selector_patterns: Vec<BuildingTypeBcaSelectorPatternSummary>,
|
||||||
pub files: Vec<BuildingTypeSourceFile>,
|
pub files: Vec<BuildingTypeSourceFile>,
|
||||||
pub entries: Vec<BuildingTypeSourceEntry>,
|
pub entries: Vec<BuildingTypeSourceEntry>,
|
||||||
}
|
}
|
||||||
|
|
@ -78,6 +107,7 @@ pub fn inspect_building_types_dir_with_bindings(
|
||||||
"bty" => BuildingTypeSourceKind::Bty,
|
"bty" => BuildingTypeSourceKind::Bty,
|
||||||
_ => continue,
|
_ => continue,
|
||||||
};
|
};
|
||||||
|
let bytes = fs::read(entry.path())?;
|
||||||
let raw_stem = Path::new(&file_name)
|
let raw_stem = Path::new(&file_name)
|
||||||
.file_stem()
|
.file_stem()
|
||||||
.and_then(|stem| stem.to_str())
|
.and_then(|stem| stem.to_str())
|
||||||
|
|
@ -90,7 +120,12 @@ pub fn inspect_building_types_dir_with_bindings(
|
||||||
file_name,
|
file_name,
|
||||||
canonical_stem: canonicalize_building_stem(&raw_stem),
|
canonical_stem: canonicalize_building_stem(&raw_stem),
|
||||||
raw_stem,
|
raw_stem,
|
||||||
source_kind,
|
source_kind: source_kind.clone(),
|
||||||
|
byte_len: Some(bytes.len()),
|
||||||
|
bca_selector_probe: match source_kind {
|
||||||
|
BuildingTypeSourceKind::Bca => Some(probe_bca_selector_bytes(&bytes)),
|
||||||
|
BuildingTypeSourceKind::Bty => None,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -141,10 +176,45 @@ pub fn inspect_building_types_dir_with_bindings(
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|file| matches!(file.source_kind, BuildingTypeSourceKind::Bty))
|
.filter(|file| matches!(file.source_kind, BuildingTypeSourceKind::Bty))
|
||||||
.count();
|
.count();
|
||||||
|
let mut grouped_selector_patterns =
|
||||||
|
BTreeMap::<(usize, String, String, String, String), Vec<String>>::new();
|
||||||
|
for file in &files {
|
||||||
|
let Some(probe) = &file.bca_selector_probe else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
grouped_selector_patterns
|
||||||
|
.entry((
|
||||||
|
file.byte_len.unwrap_or_default(),
|
||||||
|
probe.byte_0xb8_hex.clone(),
|
||||||
|
probe.byte_0xb9_hex.clone(),
|
||||||
|
probe.byte_0xba_hex.clone(),
|
||||||
|
probe.byte_0xbb_hex.clone(),
|
||||||
|
))
|
||||||
|
.or_default()
|
||||||
|
.push(file.file_name.clone());
|
||||||
|
}
|
||||||
|
let bca_selector_patterns = grouped_selector_patterns
|
||||||
|
.into_iter()
|
||||||
|
.map(
|
||||||
|
|(
|
||||||
|
(byte_len, byte_0xb8_hex, byte_0xb9_hex, byte_0xba_hex, byte_0xbb_hex),
|
||||||
|
file_names,
|
||||||
|
)| BuildingTypeBcaSelectorPatternSummary {
|
||||||
|
byte_len,
|
||||||
|
byte_0xb8_hex,
|
||||||
|
byte_0xb9_hex,
|
||||||
|
byte_0xba_hex,
|
||||||
|
byte_0xbb_hex,
|
||||||
|
file_count: file_names.len(),
|
||||||
|
sample_file_names: file_names.into_iter().take(12).collect(),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
let notes = vec![
|
let notes = vec![
|
||||||
"BuildingTypes sources are grouped by a canonical stem that lowercases and strips spaces, underscores, and hyphens so paired .bca/.bty variants collapse onto one asset token.".to_string(),
|
"BuildingTypes sources are grouped by a canonical stem that lowercases and strips spaces, underscores, and hyphens so paired .bca/.bty variants collapse onto one asset token.".to_string(),
|
||||||
"This report is an offline asset-pool view only; it does not by itself assign live candidate ids or prove scenario candidate-table availability.".to_string(),
|
"This report is an offline asset-pool view only; it does not by itself assign live candidate ids or prove scenario candidate-table availability.".to_string(),
|
||||||
|
"For .bca files, the report also exposes the narrow selector-byte window at offsets 0xb8..0xbb used by the grounded aux-candidate and live-candidate stream decoders.".to_string(),
|
||||||
];
|
];
|
||||||
|
|
||||||
let named_binding_comparison = if let Some(bindings_path) = bindings_path {
|
let named_binding_comparison = if let Some(bindings_path) = bindings_path {
|
||||||
|
|
@ -158,13 +228,32 @@ pub fn inspect_building_types_dir_with_bindings(
|
||||||
bca_file_count,
|
bca_file_count,
|
||||||
bty_file_count,
|
bty_file_count,
|
||||||
unique_canonical_stem_count: entries.len(),
|
unique_canonical_stem_count: entries.len(),
|
||||||
|
bca_selector_pattern_count: bca_selector_patterns.len(),
|
||||||
named_binding_comparison,
|
named_binding_comparison,
|
||||||
notes,
|
notes,
|
||||||
|
bca_selector_patterns,
|
||||||
files,
|
files,
|
||||||
entries,
|
entries,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn probe_bca_selector_bytes(bytes: &[u8]) -> BuildingTypeBcaSelectorProbe {
|
||||||
|
let byte_0xb8 = bytes.get(0xb8).copied().unwrap_or(0);
|
||||||
|
let byte_0xb9 = bytes.get(0xb9).copied().unwrap_or(0);
|
||||||
|
let byte_0xba = bytes.get(0xba).copied().unwrap_or(0);
|
||||||
|
let byte_0xbb = bytes.get(0xbb).copied().unwrap_or(0);
|
||||||
|
BuildingTypeBcaSelectorProbe {
|
||||||
|
byte_0xb8,
|
||||||
|
byte_0xb8_hex: format!("0x{byte_0xb8:02x}"),
|
||||||
|
byte_0xb9,
|
||||||
|
byte_0xb9_hex: format!("0x{byte_0xb9:02x}"),
|
||||||
|
byte_0xba,
|
||||||
|
byte_0xba_hex: format!("0x{byte_0xba:02x}"),
|
||||||
|
byte_0xbb,
|
||||||
|
byte_0xbb_hex: format!("0x{byte_0xbb:02x}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn load_named_binding_comparison(
|
fn load_named_binding_comparison(
|
||||||
bindings_path: &Path,
|
bindings_path: &Path,
|
||||||
entries: &[BuildingTypeSourceEntry],
|
entries: &[BuildingTypeSourceEntry],
|
||||||
|
|
@ -214,3 +303,24 @@ struct BuildingBindingRow {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
candidate_name: Option<String>,
|
candidate_name: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn probes_bca_selector_bytes_from_fixed_offsets() {
|
||||||
|
let mut bytes = vec![0u8; 0xbc + 1];
|
||||||
|
bytes[0xb8] = 0x12;
|
||||||
|
bytes[0xb9] = 0x34;
|
||||||
|
bytes[0xba] = 0x56;
|
||||||
|
bytes[0xbb] = 0x78;
|
||||||
|
let probe = probe_bca_selector_bytes(&bytes);
|
||||||
|
assert_eq!(probe.byte_0xb8, 0x12);
|
||||||
|
assert_eq!(probe.byte_0xb9, 0x34);
|
||||||
|
assert_eq!(probe.byte_0xba, 0x56);
|
||||||
|
assert_eq!(probe.byte_0xbb, 0x78);
|
||||||
|
assert_eq!(probe.byte_0xb8_hex, "0x12");
|
||||||
|
assert_eq!(probe.byte_0xbb_hex, "0x78");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -678,12 +678,15 @@ Working rule:
|
||||||
- the writer-side split is narrower now too:
|
- the writer-side split is narrower now too:
|
||||||
direct disassembly of `0x004120b0` shows that the per-record stream-load helper clears
|
direct disassembly of `0x004120b0` shows that the per-record stream-load helper clears
|
||||||
`[candidate+0x79c/+0x7a0/+0x78c/+0x790/+0x794/+0x7b0]`, restores the fixed fields through
|
`[candidate+0x79c/+0x7a0/+0x78c/+0x790/+0x794/+0x7b0]`, restores the fixed fields through
|
||||||
`[candidate+0x33]`, and streams the packed `0xbc` descriptor array into `[candidate+0x37]`,
|
`[candidate+0x33]`, restores `[candidate+0xb9/+0xba/+0xbb]`, and streams the packed `0xbc`
|
||||||
but does **not** write `[candidate+0xba/+0xbb]` in the checked body. So the next concrete
|
descriptor array into `[candidate+0x37]`. Direct disassembly of upstream source-record import
|
||||||
recovery target is now the bank-qualified template source in `0x00412d70`, not the lower
|
`0x00414490` also restores `[record+0xb8/+0xb9/+0xba/+0xbb]`. The new checked-in building
|
||||||
tagged-record reader:
|
source inspector now shows the stock `Data/BuildingTypes/*.bca` corpus keeps those four bytes
|
||||||
recover how preserved `[candidate+0xba/+0xbb]` bank/template state feeds the
|
zero across every observed file, including `Warehouse.bca` and `Port.bca`. So the next
|
||||||
`Warehouse%02d` runtime side before `0x00411ee0 / 0x00411ce0 / 0x00412c10` run.
|
concrete recovery target is no longer the lower tagged-record reader itself:
|
||||||
|
recover which later owner or alternate content path makes the live
|
||||||
|
`[candidate+0xba/+0xbb]` bank/template state diverge from that all-zero shipped BCA corpus
|
||||||
|
before `0x00411ee0 / 0x00411ce0 / 0x00412c10` run.
|
||||||
kinds”; it is the smaller set of scenario-specific records where that sweep explicitly writes
|
kinds”; it is the smaller set of scenario-specific records where that sweep explicitly writes
|
||||||
`[event+0x7ef]` itself or a still-later owner does.
|
`[event+0x7ef]` itself or a still-later owner does.
|
||||||
- two explicit trigger-kind materializations are now grounded inside that retagger:
|
- two explicit trigger-kind materializations are now grounded inside that retagger:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue