Ground placed-structure side-buffer seam
This commit is contained in:
parent
ec4919fdbf
commit
a669edcaa8
4 changed files with 82 additions and 8 deletions
|
|
@ -27,7 +27,8 @@ use rrt_runtime::{
|
||||||
SmpRt3105PackedProfileBlock, SmpSaveLoadSummary, WinInspectionReport, execute_step_command,
|
SmpRt3105PackedProfileBlock, SmpSaveLoadSummary, WinInspectionReport, execute_step_command,
|
||||||
extract_pk4_entry_file, inspect_campaign_exe_file, inspect_cargo_economy_sources_with_bindings,
|
extract_pk4_entry_file, inspect_campaign_exe_file, inspect_cargo_economy_sources_with_bindings,
|
||||||
inspect_cargo_skin_pk4, inspect_cargo_types_dir, inspect_pk4_file,
|
inspect_cargo_skin_pk4, inspect_cargo_types_dir, inspect_pk4_file,
|
||||||
inspect_save_company_and_chairman_analysis_file, inspect_smp_file,
|
inspect_save_company_and_chairman_analysis_file,
|
||||||
|
inspect_save_placed_structure_dynamic_side_buffer_file, inspect_smp_file,
|
||||||
inspect_unclassified_save_collection_headers_file, inspect_win_file,
|
inspect_unclassified_save_collection_headers_file, inspect_win_file,
|
||||||
load_runtime_snapshot_document, load_runtime_state_import, load_save_slice_file,
|
load_runtime_snapshot_document, load_runtime_state_import, load_save_slice_file,
|
||||||
project_save_slice_to_runtime_state_import, save_runtime_overlay_import_document,
|
project_save_slice_to_runtime_state_import, save_runtime_overlay_import_document,
|
||||||
|
|
@ -131,6 +132,9 @@ enum Command {
|
||||||
RuntimeInspectSaveCompanyChairman {
|
RuntimeInspectSaveCompanyChairman {
|
||||||
smp_path: PathBuf,
|
smp_path: PathBuf,
|
||||||
},
|
},
|
||||||
|
RuntimeInspectPlacedStructureDynamicSideBuffer {
|
||||||
|
smp_path: PathBuf,
|
||||||
|
},
|
||||||
RuntimeInspectUnclassifiedSaveCollections {
|
RuntimeInspectUnclassifiedSaveCollections {
|
||||||
smp_path: PathBuf,
|
smp_path: PathBuf,
|
||||||
},
|
},
|
||||||
|
|
@ -857,6 +861,9 @@ fn real_main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
Command::RuntimeInspectSaveCompanyChairman { smp_path } => {
|
Command::RuntimeInspectSaveCompanyChairman { smp_path } => {
|
||||||
run_runtime_inspect_save_company_chairman(&smp_path)?;
|
run_runtime_inspect_save_company_chairman(&smp_path)?;
|
||||||
}
|
}
|
||||||
|
Command::RuntimeInspectPlacedStructureDynamicSideBuffer { smp_path } => {
|
||||||
|
run_runtime_inspect_placed_structure_dynamic_side_buffer(&smp_path)?;
|
||||||
|
}
|
||||||
Command::RuntimeInspectUnclassifiedSaveCollections { smp_path } => {
|
Command::RuntimeInspectUnclassifiedSaveCollections { smp_path } => {
|
||||||
run_runtime_inspect_unclassified_save_collections(&smp_path)?;
|
run_runtime_inspect_unclassified_save_collections(&smp_path)?;
|
||||||
}
|
}
|
||||||
|
|
@ -1063,6 +1070,14 @@ fn parse_command() -> Result<Command, Box<dyn std::error::Error>> {
|
||||||
smp_path: PathBuf::from(path),
|
smp_path: PathBuf::from(path),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
[command, subcommand, path]
|
||||||
|
if command == "runtime"
|
||||||
|
&& subcommand == "inspect-placed-structure-dynamic-side-buffer" =>
|
||||||
|
{
|
||||||
|
Ok(Command::RuntimeInspectPlacedStructureDynamicSideBuffer {
|
||||||
|
smp_path: PathBuf::from(path),
|
||||||
|
})
|
||||||
|
}
|
||||||
[command, subcommand, path]
|
[command, subcommand, path]
|
||||||
if command == "runtime" && subcommand == "inspect-unclassified-save-collections" =>
|
if command == "runtime" && subcommand == "inspect-unclassified-save-collections" =>
|
||||||
{
|
{
|
||||||
|
|
@ -1273,7 +1288,7 @@ fn parse_command() -> Result<Command, Box<dyn std::error::Error>> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
_ => Err(
|
_ => Err(
|
||||||
"usage: rrt-cli [validate [repo-root] | finance eval <snapshot.json> | finance diff <left.json> <right.json> | runtime validate-fixture <fixture.json> | runtime summarize-fixture <fixture.json> | runtime export-fixture-state <fixture.json> <snapshot.json> | runtime diff-state <left.json> <right.json> | runtime summarize-state <snapshot.json> | runtime import-state <input.json> <snapshot.json> | runtime inspect-smp <file.smp> | runtime summarize-save-load <file.smp> | runtime load-save-slice <file.smp> | runtime inspect-save-company-chairman <file.smp> | runtime inspect-unclassified-save-collections <file.smp> | runtime import-save-state <file.smp> <snapshot.json> | runtime export-save-slice <file.smp> <save-slice.json> | runtime export-overlay-import <snapshot.json> <save-slice.json> <overlay-import.json> | runtime inspect-pk4 <file.pk4> | runtime inspect-cargo-types <CargoTypes-dir> | runtime inspect-cargo-skins <Cargo106.PK4> | runtime inspect-cargo-economy-sources <CargoTypes-dir> <Cargo106.PK4> | runtime inspect-cargo-production-selector <CargoTypes-dir> <Cargo106.PK4> | runtime inspect-cargo-price-selector <CargoTypes-dir> <Cargo106.PK4> | runtime inspect-win <file.win> | runtime extract-pk4-entry <file.pk4> <entry-name> <output-path> | runtime inspect-campaign-exe <RT3.exe> | runtime compare-classic-profile <save1.gms> <save2.gms> [saveN.gms...] | runtime compare-105-profile <save1.gms> <save2.gms> [saveN.gms...] | runtime compare-candidate-table <file1> <file2> [fileN...] | runtime compare-recipe-book-lines <file1> <file2> [fileN...] | runtime compare-setup-payload-core <file1> <file2> [fileN...] | runtime compare-setup-launch-payload <file1> <file2> [fileN...] | runtime compare-post-special-conditions-scalars <file1> <file2> [fileN...] | runtime scan-candidate-table-headers <root-dir> | runtime scan-special-conditions <root-dir> | runtime scan-aligned-runtime-rule-band <root-dir> | runtime scan-post-special-conditions-scalars <root-dir> | runtime scan-post-special-conditions-tail <root-dir> | runtime scan-recipe-book-lines <root-dir> | runtime export-profile-block <save.gms> <profile.json>]"
|
"usage: rrt-cli [validate [repo-root] | finance eval <snapshot.json> | finance diff <left.json> <right.json> | runtime validate-fixture <fixture.json> | runtime summarize-fixture <fixture.json> | runtime export-fixture-state <fixture.json> <snapshot.json> | runtime diff-state <left.json> <right.json> | runtime summarize-state <snapshot.json> | runtime import-state <input.json> <snapshot.json> | runtime inspect-smp <file.smp> | runtime summarize-save-load <file.smp> | runtime load-save-slice <file.smp> | runtime inspect-save-company-chairman <file.smp> | runtime inspect-placed-structure-dynamic-side-buffer <file.smp> | runtime inspect-unclassified-save-collections <file.smp> | runtime import-save-state <file.smp> <snapshot.json> | runtime export-save-slice <file.smp> <save-slice.json> | runtime export-overlay-import <snapshot.json> <save-slice.json> <overlay-import.json> | runtime inspect-pk4 <file.pk4> | runtime inspect-cargo-types <CargoTypes-dir> | runtime inspect-cargo-skins <Cargo106.PK4> | runtime inspect-cargo-economy-sources <CargoTypes-dir> <Cargo106.PK4> | runtime inspect-cargo-production-selector <CargoTypes-dir> <Cargo106.PK4> | runtime inspect-cargo-price-selector <CargoTypes-dir> <Cargo106.PK4> | runtime inspect-win <file.win> | runtime extract-pk4-entry <file.pk4> <entry-name> <output-path> | runtime inspect-campaign-exe <RT3.exe> | runtime compare-classic-profile <save1.gms> <save2.gms> [saveN.gms...] | runtime compare-105-profile <save1.gms> <save2.gms> [saveN.gms...] | runtime compare-candidate-table <file1> <file2> [fileN...] | runtime compare-recipe-book-lines <file1> <file2> [fileN...] | runtime compare-setup-payload-core <file1> <file2> [fileN...] | runtime compare-setup-launch-payload <file1> <file2> [fileN...] | runtime compare-post-special-conditions-scalars <file1> <file2> [fileN...] | runtime scan-candidate-table-headers <root-dir> | runtime scan-special-conditions <root-dir> | runtime scan-aligned-runtime-rule-band <root-dir> | runtime scan-post-special-conditions-scalars <root-dir> | runtime scan-post-special-conditions-tail <root-dir> | runtime scan-recipe-book-lines <root-dir> | runtime export-profile-block <save.gms> <profile.json>]"
|
||||||
.into(),
|
.into(),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
@ -1514,6 +1529,18 @@ fn run_runtime_inspect_save_company_chairman(
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn run_runtime_inspect_placed_structure_dynamic_side_buffer(
|
||||||
|
smp_path: &Path,
|
||||||
|
) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
println!(
|
||||||
|
"{}",
|
||||||
|
serde_json::to_string_pretty(&inspect_save_placed_structure_dynamic_side_buffer_file(
|
||||||
|
smp_path
|
||||||
|
)?)?
|
||||||
|
);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn run_runtime_inspect_unclassified_save_collections(
|
fn run_runtime_inspect_unclassified_save_collections(
|
||||||
smp_path: &Path,
|
smp_path: &Path,
|
||||||
) -> Result<(), Box<dyn std::error::Error>> {
|
) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
|
|
||||||
|
|
@ -125,7 +125,8 @@ pub use smp::{
|
||||||
SmpSaveWorldSelectionRoleAnalysis, SmpSaveWorldSelectionRoleAnalysisEntry,
|
SmpSaveWorldSelectionRoleAnalysis, SmpSaveWorldSelectionRoleAnalysisEntry,
|
||||||
SmpSecondaryVariantProbe, SmpSharedHeader, SmpSpecialConditionEntry, SmpSpecialConditionsProbe,
|
SmpSecondaryVariantProbe, SmpSharedHeader, SmpSpecialConditionEntry, SmpSpecialConditionsProbe,
|
||||||
inspect_save_company_and_chairman_analysis_bytes,
|
inspect_save_company_and_chairman_analysis_bytes,
|
||||||
inspect_save_company_and_chairman_analysis_file, inspect_smp_bytes, inspect_smp_file,
|
inspect_save_company_and_chairman_analysis_file,
|
||||||
|
inspect_save_placed_structure_dynamic_side_buffer_file, inspect_smp_bytes, inspect_smp_file,
|
||||||
inspect_unclassified_save_collection_headers_file, load_save_slice_file,
|
inspect_unclassified_save_collection_headers_file, load_save_slice_file,
|
||||||
load_save_slice_from_report,
|
load_save_slice_from_report,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -3126,6 +3126,35 @@ pub fn inspect_unclassified_save_collection_headers_file(
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn inspect_save_placed_structure_dynamic_side_buffer_file(
|
||||||
|
path: &Path,
|
||||||
|
) -> Result<Option<SmpSavePlacedStructureDynamicSideBufferProbe>, Box<dyn std::error::Error>> {
|
||||||
|
let bytes = fs::read(path)?;
|
||||||
|
let file_extension_hint = path
|
||||||
|
.extension()
|
||||||
|
.and_then(|extension| extension.to_str())
|
||||||
|
.map(|extension| extension.to_ascii_lowercase());
|
||||||
|
let shared_header = parse_shared_header(&bytes);
|
||||||
|
let header_variant_probe = shared_header.as_ref().map(classify_header_variant_probe);
|
||||||
|
let first_ascii_run = find_first_ascii_run(&bytes);
|
||||||
|
let early_content_probe = first_ascii_run
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|ascii_run| probe_early_content_layout(&bytes, ascii_run));
|
||||||
|
let secondary_variant_probe = early_content_probe
|
||||||
|
.as_ref()
|
||||||
|
.and_then(classify_secondary_variant_probe);
|
||||||
|
let container_profile = classify_container_profile(
|
||||||
|
file_extension_hint.as_deref(),
|
||||||
|
header_variant_probe.as_ref(),
|
||||||
|
secondary_variant_probe.as_ref(),
|
||||||
|
);
|
||||||
|
Ok(parse_save_placed_structure_dynamic_side_buffer_probe(
|
||||||
|
&bytes,
|
||||||
|
file_extension_hint.as_deref(),
|
||||||
|
container_profile.as_ref(),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn inspect_smp_bytes(bytes: &[u8]) -> SmpInspectionReport {
|
pub fn inspect_smp_bytes(bytes: &[u8]) -> SmpInspectionReport {
|
||||||
inspect_bundle_bytes(bytes, None)
|
inspect_bundle_bytes(bytes, None)
|
||||||
}
|
}
|
||||||
|
|
@ -3286,6 +3315,8 @@ pub fn load_save_slice_from_report(
|
||||||
enabled_visible_labels: probe.enabled_visible_labels.clone(),
|
enabled_visible_labels: probe.enabled_visible_labels.clone(),
|
||||||
entries: probe.entries.clone(),
|
entries: probe.entries.clone(),
|
||||||
});
|
});
|
||||||
|
let placed_structure_dynamic_side_buffer_probe =
|
||||||
|
report.save_placed_structure_dynamic_side_buffer_probe.clone();
|
||||||
let mut notes = summary.notes.clone();
|
let mut notes = summary.notes.clone();
|
||||||
if let Some(probe) = &report.save_world_selection_context_probe {
|
if let Some(probe) = &report.save_world_selection_context_probe {
|
||||||
notes.push(format!(
|
notes.push(format!(
|
||||||
|
|
@ -3441,7 +3472,7 @@ pub fn load_save_slice_from_report(
|
||||||
probe.entries.first().map(|entry| entry.profile_status_kind.as_str())
|
probe.entries.first().map(|entry| entry.profile_status_kind.as_str())
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
if let Some(probe) = &report.save_placed_structure_dynamic_side_buffer_probe {
|
if let Some(probe) = &placed_structure_dynamic_side_buffer_probe {
|
||||||
notes.push(format!(
|
notes.push(format!(
|
||||||
"Raw save also exposes the separate placed-structure dynamic-side-buffer candidate 0x38a5/0x38a6/0x38a7: live_record_count={}, first compact prefix=({},{},{}), first embedded names={:?}/{:?}, embedded 0x55f1 row count={}.",
|
"Raw save also exposes the separate placed-structure dynamic-side-buffer candidate 0x38a5/0x38a6/0x38a7: live_record_count={}, first compact prefix=({},{},{}), first embedded names={:?}/{:?}, embedded 0x55f1 row count={}.",
|
||||||
probe.live_record_count,
|
probe.live_record_count,
|
||||||
|
|
@ -3517,8 +3548,16 @@ pub fn inspect_save_company_and_chairman_analysis_bytes(
|
||||||
let region_record_triplets = report.save_region_record_triplet_probe.clone();
|
let region_record_triplets = report.save_region_record_triplet_probe.clone();
|
||||||
let placed_structure_record_triplets =
|
let placed_structure_record_triplets =
|
||||||
report.save_placed_structure_record_triplet_probe.clone();
|
report.save_placed_structure_record_triplet_probe.clone();
|
||||||
let placed_structure_dynamic_side_buffer =
|
let placed_structure_dynamic_side_buffer = report
|
||||||
report.save_placed_structure_dynamic_side_buffer_probe.clone();
|
.save_placed_structure_dynamic_side_buffer_probe
|
||||||
|
.clone()
|
||||||
|
.or_else(|| {
|
||||||
|
parse_save_placed_structure_dynamic_side_buffer_probe(
|
||||||
|
bytes,
|
||||||
|
report.file_extension_hint.as_deref(),
|
||||||
|
report.container_profile.as_ref(),
|
||||||
|
)
|
||||||
|
});
|
||||||
let unclassified_tagged_collection_headers = report
|
let unclassified_tagged_collection_headers = report
|
||||||
.save_unclassified_tagged_collection_header_probes
|
.save_unclassified_tagged_collection_header_probes
|
||||||
.clone();
|
.clone();
|
||||||
|
|
|
||||||
|
|
@ -23,8 +23,9 @@ Working rule:
|
||||||
semantics of the now-grounded compact `0x55f3` footer dword/status lane and the newly exposed
|
semantics of the now-grounded compact `0x55f3` footer dword/status lane and the newly exposed
|
||||||
separate tagged side-buffer seam candidates, especially the exact `0x38a5/0x38a6/0x38a7`
|
separate tagged side-buffer seam candidates, especially the exact `0x38a5/0x38a6/0x38a7`
|
||||||
family whose compact `6`-byte header pattern and embedded placed-structure-style `0x55f1`
|
family whose compact `6`-byte header pattern and embedded placed-structure-style `0x55f1`
|
||||||
name rows now make it the strongest current candidate for the separate placed-structure dynamic
|
name rows now make it the grounded placed-structure dynamic side-buffer owner; the remaining
|
||||||
side-buffer owner.
|
blocker is semantic closure of the 6-byte prefix lane and its relation to the embedded
|
||||||
|
`0x55f1/0x55f2/0x55f3` row subset.
|
||||||
- Extend shellless clock advancement so more periodic-company service branches consume owned
|
- Extend shellless clock advancement so more periodic-company service branches consume owned
|
||||||
runtime time state directly instead of only the explicit periodic service command.
|
runtime time state directly instead of only the explicit periodic service command.
|
||||||
- Keep widening selected-year world-owner state only when a full owning reader/rebuild family is
|
- Keep widening selected-year world-owner state only when a full owning reader/rebuild family is
|
||||||
|
|
@ -90,6 +91,12 @@ Working rule:
|
||||||
`rrt-runtime`: its synthetic regression is grounded, its header shape is checked in, and the
|
`rrt-runtime`: its synthetic regression is grounded, its header shape is checked in, and the
|
||||||
parser now expects a compact 6-byte prefix plus separator byte before an embedded
|
parser now expects a compact 6-byte prefix plus separator byte before an embedded
|
||||||
placed-structure-style dual-name row rather than treating the family as anonymous residue.
|
placed-structure-style dual-name row rather than treating the family as anonymous residue.
|
||||||
|
- That exact `0x38a5/0x38a6/0x38a7` parser is now also wired through a lightweight CLI inspector
|
||||||
|
and the normal save company/chairman analysis output, and grounded real saves now prove the
|
||||||
|
same seam directly:
|
||||||
|
`q.gms` exposes `live_record_count=3865`, prefix `0x0005d368/0x0001/0xff`, and first embedded
|
||||||
|
names `TrackCapST_Cap.3dp` / `Infrastructure`; `p.gms` exposes the same structure with
|
||||||
|
`live_record_count=2467`.
|
||||||
- The placed-structure tagged save stream now also exposes repeated `0x55f1/0x55f2/0x55f3`
|
- The placed-structure tagged save stream now also exposes repeated `0x55f1/0x55f2/0x55f3`
|
||||||
triplets with dual name stems, a fixed five-`f32` policy row, and a compact `0x5dc1...0x5dc2`
|
triplets with dual name stems, a fixed five-`f32` policy row, and a compact `0x5dc1...0x5dc2`
|
||||||
footer carrying one raw `u32` payload lane plus one live `i32` status lane, so the remaining
|
footer carrying one raw `u32` payload lane plus one live `i32` status lane, so the remaining
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue