From dad929130834bcf75c6b587ff12805027c0a937f Mon Sep 17 00:00:00 2001 From: Jan Petykiewicz Date: Fri, 17 Apr 2026 18:58:41 -0700 Subject: [PATCH] Probe fixed-world finance neighborhood --- README.md | 5 +- crates/rrt-runtime/src/smp.rs | 152 ++++++++++++++++++++++++++++++++++ docs/README.md | 5 +- docs/runtime-rehost-plan.md | 5 +- 4 files changed, 161 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 1ba38c7..9a7b4ab 100644 --- a/README.md +++ b/README.md @@ -43,8 +43,9 @@ surface also now exposes `runtime inspect-save-company-chairman ` for company/chairman scalar candidates, including fixed-world chairman slot / role-gate context, explicit company dword candidate windows, richer chairman qword cache views, and derived holdings-at-share-price / cached purchasing-power comparisons. The same fixed `0x32c8` world -block is now probed for both the grounded issue-`0x37` pair at `[world+0x29/+0x2d]` and the -separate six-float economic tuning band, but current atlas evidence still keeps that editor-facing +block is now probed for the grounded issue-`0x37` pair at `[world+0x29/+0x2d]`, one broader +fixed-dword finance neighborhood around the absolute-calendar and issue lanes, and the separate +six-float economic tuning band, but current atlas evidence still keeps that editor-facing tuning family distinct from the governance issue lanes behind investor confidence and prime-rate math. The next shared company-side slice is now rehosted too: save-native company direct records flow into a typed company market/cache map on runtime service state, carrying outstanding shares, diff --git a/crates/rrt-runtime/src/smp.rs b/crates/rrt-runtime/src/smp.rs index 821d00a..24c83d4 100644 --- a/crates/rrt-runtime/src/smp.rs +++ b/crates/rrt-runtime/src/smp.rs @@ -97,6 +97,18 @@ const RT3_SAVE_WORLD_BLOCK_SELECTED_COMPANY_ID_RELATIVE_OFFSET: usize = 0x1d; const RT3_SAVE_WORLD_BLOCK_SELECTED_CHAIRMAN_PROFILE_ID_RELATIVE_OFFSET: usize = 0x21; const RT3_SAVE_WORLD_BLOCK_ISSUE_0X37_MULTIPLIER_RELATIVE_OFFSET: usize = 0x25; const RT3_SAVE_WORLD_BLOCK_ISSUE_0X37_VALUE_RELATIVE_OFFSET: usize = 0x29; +const RT3_SAVE_WORLD_BLOCK_FINANCE_NEIGHBORHOOD_CANDIDATE_FIELDS: [(&str, usize); 10] = [ + ("absolute_calendar_counter_candidate_0", 0x11), + ("absolute_calendar_counter_candidate_1", 0x15), + ("absolute_calendar_counter_candidate_2", 0x19), + ("selection_context_candidate_0", 0x1d), + ("selection_context_candidate_1", 0x21), + ("issue_0x37_multiplier", 0x25), + ("issue_0x37_value", 0x29), + ("issue_neighbor_candidate_0", 0x2d), + ("issue_neighbor_candidate_1", 0x31), + ("issue_neighbor_candidate_2", 0x35), +]; const RT3_SAVE_WORLD_BLOCK_CHAIRMAN_SLOT_SELECTOR_RELATIVE_OFFSET: usize = 0x83; const RT3_SAVE_WORLD_BLOCK_CAMPAIGN_OVERRIDE_FLAG_RELATIVE_OFFSET: usize = 0xc1; const RT3_SAVE_WORLD_BLOCK_CHAIRMAN_ROLE_GATE_RELATIVE_OFFSET: usize = 0x0bbf; @@ -1512,6 +1524,19 @@ pub struct SmpSaveWorldIssue37Probe { pub evidence: Vec, } +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub struct SmpSaveWorldFinanceNeighborhoodProbe { + pub profile_family: String, + pub source_kind: String, + pub semantic_family: String, + pub chunk_tag_offset: usize, + pub payload_offset: usize, + pub payload_len: usize, + pub payload_len_hex: String, + pub dword_candidates: Vec, + pub evidence: Vec, +} + #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub struct SmpSaveTaggedCollectionHeaderProbe { pub profile_family: String, @@ -2341,6 +2366,8 @@ pub struct SmpSaveCompanyChairmanAnalysisReport { #[serde(default)] pub world_economic_tuning: Option, #[serde(default)] + pub world_finance_neighborhood: Option, + #[serde(default)] pub company_entries: Vec, #[serde(default)] pub chairman_entries: Vec, @@ -2592,6 +2619,7 @@ pub struct SmpInspectionReport { pub save_world_selection_context_probe: Option, pub save_world_issue_37_probe: Option, pub save_world_economic_tuning_probe: Option, + pub save_world_finance_neighborhood_probe: Option, pub save_company_collection_header_probe: Option, pub save_chairman_profile_collection_header_probe: Option, #[serde(default)] @@ -2906,6 +2934,7 @@ pub fn inspect_save_company_and_chairman_analysis_bytes( let world_selection_context = selection_probe.map(build_save_world_selection_role_analysis); let world_issue_37 = report.save_world_issue_37_probe.clone(); let world_economic_tuning = report.save_world_economic_tuning_probe.clone(); + let world_finance_neighborhood = report.save_world_finance_neighborhood_probe.clone(); let company_header_probe = report.save_company_collection_header_probe.as_ref(); let chairman_header_probe = report .save_chairman_profile_collection_header_probe @@ -3128,6 +3157,12 @@ pub fn inspect_save_company_and_chairman_analysis_bytes( .to_string(), ); } + if world_finance_neighborhood.is_some() { + notes.push( + "World analysis now also exports one fixed dword finance neighborhood around the grounded issue/calendar lanes, so future issue-0x38/0x39 closure can build on rehosted owner-state candidates instead of ad hoc byte guesses." + .to_string(), + ); + } if !company_entries.is_empty() { notes.push( "Company debt is derived from the grounded bond table at [company+0x5b/+0x5f] by summing live principal slots.".to_string(), @@ -3165,6 +3200,7 @@ pub fn inspect_save_company_and_chairman_analysis_bytes( world_selection_context, world_issue_37, world_economic_tuning, + world_finance_neighborhood, company_entries, chairman_entries, notes, @@ -6664,6 +6700,11 @@ fn inspect_bundle_bytes(bytes: &[u8], file_extension_hint: Option) -> Sm file_extension_hint.as_deref(), container_profile.as_ref(), ); + let save_world_finance_neighborhood_probe = parse_save_world_finance_neighborhood_probe( + bytes, + file_extension_hint.as_deref(), + container_profile.as_ref(), + ); let save_company_collection_header_probe = parse_save_company_collection_header_probe( bytes, file_extension_hint.as_deref(), @@ -6835,6 +6876,7 @@ fn inspect_bundle_bytes(bytes: &[u8], file_extension_hint: Option) -> Sm save_world_selection_context_probe, save_world_issue_37_probe, save_world_economic_tuning_probe, + save_world_finance_neighborhood_probe, save_company_collection_header_probe, save_chairman_profile_collection_header_probe, save_company_roster_probe, @@ -8436,6 +8478,64 @@ fn parse_save_world_issue_37_probe( None } +fn parse_save_world_finance_neighborhood_probe( + bytes: &[u8], + file_extension_hint: Option<&str>, + container_profile: Option<&SmpContainerProfile>, +) -> Option { + if file_extension_hint != Some("gms") { + return None; + } + let profile = container_profile?; + let supported = matches!( + profile.profile_family.as_str(), + "rt3-classic-save-container-v1" + | "rt3-105-save-container-v1" + | "rt3-105-scenario-save-container-v1" + | "rt3-105-alt-save-container-v1" + ); + if !supported { + return None; + } + + for chunk_tag_offset in find_u32_le_offsets(bytes, RT3_SAVE_WORLD_BLOCK_CHUNK_TAG) { + let payload_offset = chunk_tag_offset + 4; + let next_chunk_tag_offset = payload_offset.checked_add(RT3_SAVE_WORLD_BLOCK_LEN)?; + if read_u32_at(bytes, next_chunk_tag_offset) != Some(RT3_SAVE_WORLD_BLOCK_NEXT_CHUNK_TAG) { + continue; + } + + let dword_candidates = RT3_SAVE_WORLD_BLOCK_FINANCE_NEIGHBORHOOD_CANDIDATE_FIELDS + .iter() + .map(|(label, relative_offset)| { + build_save_dword_candidate(bytes, payload_offset, label, *relative_offset) + }) + .collect::>>()?; + + return Some(SmpSaveWorldFinanceNeighborhoodProbe { + profile_family: profile.profile_family.clone(), + source_kind: "save-direct-world-block".to_string(), + semantic_family: "scenario-save-world-finance-neighborhood".to_string(), + chunk_tag_offset, + payload_offset, + payload_len: RT3_SAVE_WORLD_BLOCK_LEN, + payload_len_hex: format!("0x{:x}", RT3_SAVE_WORLD_BLOCK_LEN), + dword_candidates, + evidence: vec![ + format!( + "chunk tag 0x32c8 at 0x{chunk_tag_offset:x} matches the fixed [world+0x04] save block" + ), + format!( + "next chunk tag 0x32c9 appears at 0x{next_chunk_tag_offset:x}, matching the documented 0x4f2c payload span" + ), + "finance-neighborhood candidates cover the fixed dword strip around the grounded world absolute-calendar, selection-context, and issue-0x37 lanes so broader issue-state closure can build on one rehosted owner surface.".to_string(), + ], + }); + } + + None +} + fn parse_save_world_economic_tuning_probe( bytes: &[u8], file_extension_hint: Option<&str>, @@ -15124,6 +15224,58 @@ mod tests { assert!((probe.multiplier_lane.value_f32 - 0.06).abs() < f32::EPSILON); } + #[test] + fn parses_save_world_finance_neighborhood_probe_from_fixed_world_block() { + let mut bytes = vec![0u8; 0x8000]; + let chunk_tag_offset = 0x3ceusize; + let payload_offset = chunk_tag_offset + 4; + bytes[chunk_tag_offset..chunk_tag_offset + 4] + .copy_from_slice(&RT3_SAVE_WORLD_BLOCK_CHUNK_TAG.to_le_bytes()); + for (index, (_, relative_offset)) in + RT3_SAVE_WORLD_BLOCK_FINANCE_NEIGHBORHOOD_CANDIDATE_FIELDS + .iter() + .enumerate() + { + bytes[payload_offset + *relative_offset..payload_offset + *relative_offset + 4] + .copy_from_slice(&((index as u32) + 1).to_le_bytes()); + } + let next_chunk_offset = payload_offset + RT3_SAVE_WORLD_BLOCK_LEN; + bytes[next_chunk_offset..next_chunk_offset + 4] + .copy_from_slice(&RT3_SAVE_WORLD_BLOCK_NEXT_CHUNK_TAG.to_le_bytes()); + + let probe = parse_save_world_finance_neighborhood_probe( + &bytes, + Some("gms"), + Some(&SmpContainerProfile { + profile_family: "rt3-105-save-container-v1".to_string(), + profile_evidence: vec![], + is_known_profile: true, + }), + ) + .expect("world finance neighborhood probe should parse"); + + assert_eq!(probe.chunk_tag_offset, chunk_tag_offset); + assert_eq!(probe.payload_offset, payload_offset); + assert_eq!( + probe.dword_candidates.len(), + RT3_SAVE_WORLD_BLOCK_FINANCE_NEIGHBORHOOD_CANDIDATE_FIELDS.len() + ); + assert_eq!( + probe.dword_candidates[0].label, + "absolute_calendar_counter_candidate_0" + ); + assert_eq!(probe.dword_candidates[0].relative_offset_hex, "0x11"); + assert_eq!(probe.dword_candidates[0].value_i32, 1); + assert_eq!(probe.dword_candidates[5].label, "issue_0x37_multiplier"); + assert_eq!(probe.dword_candidates[5].relative_offset_hex, "0x25"); + assert_eq!( + probe.dword_candidates[9].label, + "issue_neighbor_candidate_2" + ); + assert_eq!(probe.dword_candidates[9].relative_offset_hex, "0x35"); + assert_eq!(probe.dword_candidates[9].value_i32, 10); + } + #[test] fn loads_selection_only_company_and_chairman_context_from_save_world_probe() { let mut report = inspect_smp_bytes(&[]); diff --git a/docs/README.md b/docs/README.md index 85d42f9..1ca4c6d 100644 --- a/docs/README.md +++ b/docs/README.md @@ -107,8 +107,9 @@ The highest-value next passes are now: defaults until their raw offsets are pinned more strongly; the offline analysis command `runtime inspect-save-company-chairman ` now dumps those remaining raw record candidates directly from the rehosted parser, including fixed-world chairman slot / role-gate - context, the grounded fixed-world issue-`0x37` pair, the separate six-float economic tuning - band, derived holdings-at-share-price and cached purchasing-power totals, + context, the grounded fixed-world issue-`0x37` pair, the fixed-dword world finance + neighborhood around the absolute-calendar and issue lanes, the separate six-float economic + tuning band, derived holdings-at-share-price and cached purchasing-power totals, context, company dword candidate windows, and richer chairman qword cache views; the current rehosted company-side owner state now also includes a typed market/cache map carrying saved outstanding-shares, support/share-price/cache words, salary lanes, calendar words, and diff --git a/docs/runtime-rehost-plan.md b/docs/runtime-rehost-plan.md index ef186f8..323f286 100644 --- a/docs/runtime-rehost-plan.md +++ b/docs/runtime-rehost-plan.md @@ -66,8 +66,9 @@ Implemented today: from the bond table and raw company track-laying capacity from the record tail are grounded too, and chairman purchasing power now reuses the strongest nonnegative cached qword total from the `[profile+0x1e9..]` band plus current cash instead of collapsing to plain net worth; - the same fixed world payload now exposes the grounded issue-`0x37` pair at `[world+0x29/+0x2d]` - and the separate six-float economic tuning band `[world+0x0be2..+0x0bf6]` through save + the same fixed world payload now exposes the grounded issue-`0x37` pair at `[world+0x29/+0x2d]`, + one broader fixed-dword finance neighborhood around the absolute-calendar and nearby issue + lanes, and the separate six-float economic tuning band `[world+0x0be2..+0x0bf6]` through save inspection too, but current atlas evidence still keeps that editor-tuning family separate from the company-governance issue lanes; the next shared company-side owning state is rehosted now too, because save-native company direct records now project into a typed runtime