Rehost selected-year bucket companion bands

This commit is contained in:
Jan Petykiewicz 2026-04-18 07:06:30 -07:00
commit b5d194f678
9 changed files with 326 additions and 20 deletions

View file

@ -129,7 +129,10 @@ living only as ad hoc world flags.
The selected-year seam is now doing the same thing: the checked-in `0x00433bd0` year ladder now The selected-year seam is now doing the same thing: the checked-in `0x00433bd0` year ladder now
drives a derived selected-year bucket scalar in runtime restore state, and the economic-tuning drives a derived selected-year bucket scalar in runtime restore state, and the economic-tuning
mirror `[world+0x0bde]` now rebuilds from tuning lane `0` instead of freezing one stale load-time mirror `[world+0x0bde]` now rebuilds from tuning lane `0` instead of freezing one stale load-time
word. word. That same checked-in owner family now also rebuilds the direct bucket trio
`[world+0x65/+0x69/+0x6d]`, the complement trio `[world+0x71/+0x75/+0x79]`, and the scaled
companion trio `[world+0x7d/+0x81/+0x85]` from the selected-year bucket scalar instead of
preserving stale save-time residue.
Those bankruptcy branches now follow the grounded owner semantics too: they stamp the bankruptcy Those bankruptcy branches now follow the grounded owner semantics too: they stamp the bankruptcy
year and halve live bond principals in place instead of treating bankruptcy as a liquidation path. year and halve live bond principals in place instead of treating bankruptcy as a liquidation path.
The same save-native live bond-slot surface now also carries per-slot maturity years all the way The same save-native live bond-slot surface now also carries per-slot maturity years all the way

View file

@ -5,6 +5,26 @@
"pair_count": 21, "pair_count": 21,
"terminal_scalar_virtual_address": "0x005f3a24", "terminal_scalar_virtual_address": "0x005f3a24",
"terminal_scalar_value": 123.0, "terminal_scalar_value": 123.0,
"direct_lane_multipliers": [
0.9,
1.05,
0.7
],
"complement_formula": {
"divisor": 50.0,
"multiplier": 0.65,
"bias": 0.35,
"scale": 0.001190483570098877,
"floor": 0.0001,
"build_106_multiplier": 1.15,
"cap": 0.15
},
"scaled_companion_formula": {
"numerator": 50.0,
"multiplier": 0.7,
"bias": 0.3,
"scale": 75.0
},
"entries": [ "entries": [
{ {
"year": 1800, "year": 1800,

View file

@ -982,6 +982,12 @@ fn project_save_slice_components(
.cached_available_locomotive_rating_value_f32_text .cached_available_locomotive_rating_value_f32_text
.clone() .clone()
}), }),
selected_year_bucket_direct_lane_raw_u32: Vec::new(),
selected_year_bucket_direct_lane_value_f32_text: Vec::new(),
selected_year_bucket_complement_lane_raw_u32: Vec::new(),
selected_year_bucket_complement_lane_value_f32_text: Vec::new(),
selected_year_bucket_scaled_companion_lane_raw_u32: Vec::new(),
selected_year_bucket_scaled_companion_lane_value_f32_text: Vec::new(),
selected_year_bucket_scalar_raw_u32: None, selected_year_bucket_scalar_raw_u32: None,
selected_year_bucket_scalar_value_f32_text: None, selected_year_bucket_scalar_value_f32_text: None,
selected_year_gap_scalar_raw_u32: None, selected_year_gap_scalar_raw_u32: None,

View file

@ -1423,6 +1423,18 @@ pub struct RuntimeWorldRestoreState {
#[serde(default)] #[serde(default)]
pub selected_year_bucket_scalar_value_f32_text: Option<String>, pub selected_year_bucket_scalar_value_f32_text: Option<String>,
#[serde(default)] #[serde(default)]
pub selected_year_bucket_direct_lane_raw_u32: Vec<u32>,
#[serde(default)]
pub selected_year_bucket_direct_lane_value_f32_text: Vec<String>,
#[serde(default)]
pub selected_year_bucket_complement_lane_raw_u32: Vec<u32>,
#[serde(default)]
pub selected_year_bucket_complement_lane_value_f32_text: Vec<String>,
#[serde(default)]
pub selected_year_bucket_scaled_companion_lane_raw_u32: Vec<u32>,
#[serde(default)]
pub selected_year_bucket_scaled_companion_lane_value_f32_text: Vec<String>,
#[serde(default)]
pub selected_year_gap_scalar_raw_u32: Option<u32>, pub selected_year_gap_scalar_raw_u32: Option<u32>,
#[serde(default)] #[serde(default)]
pub selected_year_gap_scalar_value_f32_text: Option<String>, pub selected_year_gap_scalar_value_f32_text: Option<String>,
@ -2423,6 +2435,37 @@ impl RuntimeState {
self.world_restore.selected_year_bucket_scalar_raw_u32 = Some(value.to_bits()); self.world_restore.selected_year_bucket_scalar_raw_u32 = Some(value.to_bits());
self.world_restore self.world_restore
.selected_year_bucket_scalar_value_f32_text = Some(format!("{value:.6}")); .selected_year_bucket_scalar_value_f32_text = Some(format!("{value:.6}"));
if let Some(bands) = runtime_selected_year_bucket_bands_from_scalar(value) {
self.world_restore.selected_year_bucket_direct_lane_raw_u32 =
bands.direct.iter().map(|lane| lane.to_bits()).collect();
self.world_restore
.selected_year_bucket_direct_lane_value_f32_text = bands
.direct
.iter()
.map(|lane| format!("{lane:.6}"))
.collect();
self.world_restore
.selected_year_bucket_complement_lane_raw_u32 =
bands.complement.iter().map(|lane| lane.to_bits()).collect();
self.world_restore
.selected_year_bucket_complement_lane_value_f32_text = bands
.complement
.iter()
.map(|lane| format!("{lane:.6}"))
.collect();
self.world_restore
.selected_year_bucket_scaled_companion_lane_raw_u32 = bands
.scaled_companion
.iter()
.map(|lane| lane.to_bits())
.collect();
self.world_restore
.selected_year_bucket_scaled_companion_lane_value_f32_text = bands
.scaled_companion
.iter()
.map(|lane| format!("{lane:.6}"))
.collect();
}
} }
if let Some(value) = runtime_world_selected_year_gap_scalar_from_year_word(year_word) { if let Some(value) = runtime_world_selected_year_gap_scalar_from_year_word(year_word) {
self.world_restore.selected_year_gap_scalar_raw_u32 = Some(value.to_bits()); self.world_restore.selected_year_gap_scalar_raw_u32 = Some(value.to_bits());
@ -2455,6 +2498,9 @@ impl RuntimeState {
#[derive(Debug, Clone, Deserialize)] #[derive(Debug, Clone, Deserialize)]
struct CheckedInSelectedYearBucketLadderArtifact { struct CheckedInSelectedYearBucketLadderArtifact {
direct_lane_multipliers: Vec<f32>,
complement_formula: CheckedInSelectedYearBucketComplementFormula,
scaled_companion_formula: CheckedInSelectedYearBucketScaledCompanionFormula,
entries: Vec<CheckedInSelectedYearBucketLadderEntry>, entries: Vec<CheckedInSelectedYearBucketLadderEntry>,
} }
@ -2464,21 +2510,44 @@ struct CheckedInSelectedYearBucketLadderEntry {
value: f32, value: f32,
} }
fn checked_in_selected_year_bucket_ladder() -> &'static [CheckedInSelectedYearBucketLadderEntry] { #[derive(Debug, Clone, Deserialize)]
static LADDER: OnceLock<Vec<CheckedInSelectedYearBucketLadderEntry>> = OnceLock::new(); struct CheckedInSelectedYearBucketComplementFormula {
LADDER divisor: f32,
.get_or_init(|| { multiplier: f32,
serde_json::from_str::<CheckedInSelectedYearBucketLadderArtifact>(include_str!( bias: f32,
"../../../artifacts/exports/rt3-1.06/selected-year-bucket-ladder.json" scale: f32,
)) floor: f32,
.expect("checked-in selected-year bucket ladder should parse") build_106_multiplier: f32,
.entries cap: f32,
}) }
.as_slice()
#[derive(Debug, Clone, Deserialize)]
struct CheckedInSelectedYearBucketScaledCompanionFormula {
numerator: f32,
multiplier: f32,
bias: f32,
scale: f32,
}
#[derive(Debug, Clone)]
struct RuntimeSelectedYearBucketBands {
direct: [f32; 3],
complement: [f32; 3],
scaled_companion: [f32; 3],
}
fn checked_in_selected_year_bucket_ladder() -> &'static CheckedInSelectedYearBucketLadderArtifact {
static LADDER: OnceLock<CheckedInSelectedYearBucketLadderArtifact> = OnceLock::new();
LADDER.get_or_init(|| {
serde_json::from_str::<CheckedInSelectedYearBucketLadderArtifact>(include_str!(
"../../../artifacts/exports/rt3-1.06/selected-year-bucket-ladder.json"
))
.expect("checked-in selected-year bucket ladder should parse")
})
} }
pub fn runtime_world_selected_year_bucket_scalar_from_year_word(year_word: u32) -> Option<f32> { pub fn runtime_world_selected_year_bucket_scalar_from_year_word(year_word: u32) -> Option<f32> {
let ladder = checked_in_selected_year_bucket_ladder(); let ladder = &checked_in_selected_year_bucket_ladder().entries;
if ladder.is_empty() { if ladder.is_empty() {
return None; return None;
} }
@ -2500,6 +2569,41 @@ pub fn runtime_world_selected_year_bucket_scalar_from_year_word(year_word: u32)
ladder.last().map(|entry| entry.value) ladder.last().map(|entry| entry.value)
} }
fn runtime_selected_year_bucket_bands_from_scalar(
scalar: f32,
) -> Option<RuntimeSelectedYearBucketBands> {
let artifact = checked_in_selected_year_bucket_ladder();
if artifact.direct_lane_multipliers.len() != 3 {
return None;
}
let direct = [
scalar * artifact.direct_lane_multipliers[0],
scalar * artifact.direct_lane_multipliers[1],
scalar * artifact.direct_lane_multipliers[2],
];
let mut complement = [0.0f32; 3];
let mut scaled_companion = [0.0f32; 3];
for (index, direct_value) in direct.iter().copied().enumerate() {
let mut x = (((direct_value / artifact.complement_formula.divisor)
* artifact.complement_formula.multiplier)
+ artifact.complement_formula.bias)
* artifact.complement_formula.scale;
x = x.max(artifact.complement_formula.floor);
x *= artifact.complement_formula.build_106_multiplier;
x = x.min(artifact.complement_formula.cap);
complement[index] = 1.0 - x;
scaled_companion[index] = (((artifact.scaled_companion_formula.numerator / direct_value)
* artifact.scaled_companion_formula.multiplier)
+ artifact.scaled_companion_formula.bias)
* artifact.scaled_companion_formula.scale;
}
Some(RuntimeSelectedYearBucketBands {
direct,
complement,
scaled_companion,
})
}
pub fn runtime_world_selected_year_gap_scalar_from_year_word(year_word: u32) -> Option<f32> { pub fn runtime_world_selected_year_gap_scalar_from_year_word(year_word: u32) -> Option<f32> {
let normalized = (year_word as f64 - 1850.0) / 150.0; let normalized = (year_word as f64 - 1850.0) / 150.0;
if !normalized.is_finite() { if !normalized.is_finite() {
@ -5134,6 +5238,12 @@ mod tests {
economic_tuning_lane_value_f32_text: Vec::new(), economic_tuning_lane_value_f32_text: Vec::new(),
selected_year_bucket_scalar_raw_u32: None, selected_year_bucket_scalar_raw_u32: None,
selected_year_bucket_scalar_value_f32_text: None, selected_year_bucket_scalar_value_f32_text: None,
selected_year_bucket_direct_lane_raw_u32: Vec::new(),
selected_year_bucket_direct_lane_value_f32_text: Vec::new(),
selected_year_bucket_complement_lane_raw_u32: Vec::new(),
selected_year_bucket_complement_lane_value_f32_text: Vec::new(),
selected_year_bucket_scaled_companion_lane_raw_u32: Vec::new(),
selected_year_bucket_scaled_companion_lane_value_f32_text: Vec::new(),
selected_year_gap_scalar_raw_u32: None, selected_year_gap_scalar_raw_u32: None,
selected_year_gap_scalar_value_f32_text: None, selected_year_gap_scalar_value_f32_text: None,
absolute_counter_restore_kind: Some( absolute_counter_restore_kind: Some(
@ -8136,6 +8246,13 @@ mod tests {
runtime_world_selected_year_bucket_scalar_from_year_word(2000), runtime_world_selected_year_bucket_scalar_from_year_word(2000),
Some(123.0) Some(123.0)
); );
let bands = runtime_selected_year_bucket_bands_from_scalar(25.0)
.expect("selected-year bucket companion bands");
assert!((bands.direct[0] - 22.5).abs() < 1e-6);
assert!((bands.direct[1] - 26.25).abs() < 1e-5);
assert!((bands.direct[2] - 17.5).abs() < 1e-6);
assert!((bands.complement[0] - 0.999121).abs() < 1e-6);
assert!((bands.scaled_companion[0] - 139.16667).abs() < 1e-4);
assert_eq!( assert_eq!(
runtime_world_selected_year_gap_scalar_from_year_word(1830), runtime_world_selected_year_gap_scalar_from_year_word(1830),
Some((1.0f32 / 3.0).clamp(1.0 / 3.0, 1.0)) Some((1.0f32 / 3.0).clamp(1.0 / 3.0, 1.0))
@ -8224,6 +8341,36 @@ mod tests {
.as_deref(), .as_deref(),
Some("70.000000") Some("70.000000")
); );
assert_eq!(
state
.world_restore
.selected_year_bucket_direct_lane_value_f32_text,
vec![
"63.000000".to_string(),
"73.500000".to_string(),
"49.000000".to_string()
]
);
assert_eq!(
state
.world_restore
.selected_year_bucket_complement_lane_value_f32_text,
vec![
"0.998400".to_string(),
"0.998213".to_string(),
"0.998649".to_string()
]
);
assert_eq!(
state
.world_restore
.selected_year_bucket_scaled_companion_lane_value_f32_text,
vec![
"64.166672".to_string(),
"58.214291".to_string(),
"76.071426".to_string()
]
);
assert_eq!( assert_eq!(
state.world_restore.selected_year_gap_scalar_raw_u32, state.world_restore.selected_year_gap_scalar_raw_u32,
Some(((50.0f32 / 150.0).clamp(1.0 / 3.0, 1.0)).to_bits()) Some(((50.0f32 / 150.0).clamp(1.0 / 3.0, 1.0)).to_bits())

View file

@ -82,6 +82,12 @@ pub struct RuntimeSummary {
pub world_restore_cached_available_locomotive_rating_value_f32_text: Option<String>, pub world_restore_cached_available_locomotive_rating_value_f32_text: Option<String>,
pub world_restore_selected_year_bucket_scalar_raw_u32: Option<u32>, pub world_restore_selected_year_bucket_scalar_raw_u32: Option<u32>,
pub world_restore_selected_year_bucket_scalar_value_f32_text: Option<String>, pub world_restore_selected_year_bucket_scalar_value_f32_text: Option<String>,
pub world_restore_selected_year_bucket_direct_lane_count: usize,
pub world_restore_selected_year_bucket_direct_lane_value_f32_text: Vec<String>,
pub world_restore_selected_year_bucket_complement_lane_count: usize,
pub world_restore_selected_year_bucket_complement_lane_value_f32_text: Vec<String>,
pub world_restore_selected_year_bucket_scaled_companion_lane_count: usize,
pub world_restore_selected_year_bucket_scaled_companion_lane_value_f32_text: Vec<String>,
pub world_restore_selected_year_gap_scalar_raw_u32: Option<u32>, pub world_restore_selected_year_gap_scalar_raw_u32: Option<u32>,
pub world_restore_selected_year_gap_scalar_value_f32_text: Option<String>, pub world_restore_selected_year_gap_scalar_value_f32_text: Option<String>,
pub world_restore_absolute_counter_restore_kind: Option<String>, pub world_restore_absolute_counter_restore_kind: Option<String>,
@ -480,6 +486,30 @@ impl RuntimeSummary {
.world_restore .world_restore
.selected_year_bucket_scalar_value_f32_text .selected_year_bucket_scalar_value_f32_text
.clone(), .clone(),
world_restore_selected_year_bucket_direct_lane_count: state
.world_restore
.selected_year_bucket_direct_lane_raw_u32
.len(),
world_restore_selected_year_bucket_direct_lane_value_f32_text: state
.world_restore
.selected_year_bucket_direct_lane_value_f32_text
.clone(),
world_restore_selected_year_bucket_complement_lane_count: state
.world_restore
.selected_year_bucket_complement_lane_raw_u32
.len(),
world_restore_selected_year_bucket_complement_lane_value_f32_text: state
.world_restore
.selected_year_bucket_complement_lane_value_f32_text
.clone(),
world_restore_selected_year_bucket_scaled_companion_lane_count: state
.world_restore
.selected_year_bucket_scaled_companion_lane_raw_u32
.len(),
world_restore_selected_year_bucket_scaled_companion_lane_value_f32_text: state
.world_restore
.selected_year_bucket_scaled_companion_lane_value_f32_text
.clone(),
world_restore_selected_year_gap_scalar_raw_u32: state world_restore_selected_year_gap_scalar_raw_u32: state
.world_restore .world_restore
.selected_year_gap_scalar_raw_u32, .selected_year_gap_scalar_raw_u32,
@ -1818,6 +1848,36 @@ mod tests {
cached_available_locomotive_rating_value_f32_text: Some("20.000000".to_string()), cached_available_locomotive_rating_value_f32_text: Some("20.000000".to_string()),
selected_year_bucket_scalar_raw_u32: Some(25.0f32.to_bits()), selected_year_bucket_scalar_raw_u32: Some(25.0f32.to_bits()),
selected_year_bucket_scalar_value_f32_text: Some("25.000000".to_string()), selected_year_bucket_scalar_value_f32_text: Some("25.000000".to_string()),
selected_year_bucket_direct_lane_raw_u32: vec![
22.5f32.to_bits(),
26.25f32.to_bits(),
17.5f32.to_bits(),
],
selected_year_bucket_direct_lane_value_f32_text: vec![
"22.500000".to_string(),
"26.250000".to_string(),
"17.500000".to_string(),
],
selected_year_bucket_complement_lane_raw_u32: vec![
0.999121f32.to_bits(),
0.998998f32.to_bits(),
0.999210f32.to_bits(),
],
selected_year_bucket_complement_lane_value_f32_text: vec![
"0.999121".to_string(),
"0.998998".to_string(),
"0.999210".to_string(),
],
selected_year_bucket_scaled_companion_lane_raw_u32: vec![
139.16667f32.to_bits(),
122.5f32.to_bits(),
171.42857f32.to_bits(),
],
selected_year_bucket_scaled_companion_lane_value_f32_text: vec![
"139.166672".to_string(),
"122.500000".to_string(),
"171.428574".to_string(),
],
selected_year_gap_scalar_raw_u32: Some(0x3eaaaaab), selected_year_gap_scalar_raw_u32: Some(0x3eaaaaab),
selected_year_gap_scalar_value_f32_text: Some("0.333333".to_string()), selected_year_gap_scalar_value_f32_text: Some("0.333333".to_string()),
..RuntimeWorldRestoreState::default() ..RuntimeWorldRestoreState::default()
@ -1982,6 +2042,30 @@ mod tests {
.as_deref(), .as_deref(),
Some("25.000000") Some("25.000000")
); );
assert_eq!(
summary.world_restore_selected_year_bucket_direct_lane_count,
3
);
assert_eq!(
summary.world_restore_selected_year_bucket_direct_lane_value_f32_text,
vec!["22.500000", "26.250000", "17.500000"]
);
assert_eq!(
summary.world_restore_selected_year_bucket_complement_lane_count,
3
);
assert_eq!(
summary.world_restore_selected_year_bucket_complement_lane_value_f32_text,
vec!["0.999121", "0.998998", "0.999210"]
);
assert_eq!(
summary.world_restore_selected_year_bucket_scaled_companion_lane_count,
3
);
assert_eq!(
summary.world_restore_selected_year_bucket_scaled_companion_lane_value_f32_text,
vec!["139.166672", "122.500000", "171.428574"]
);
assert_eq!(summary.world_restore_economic_tuning_lane_count, 6); assert_eq!(summary.world_restore_economic_tuning_lane_count, 6);
assert_eq!( assert_eq!(
summary.world_restore_economic_tuning_lane_value_f32_text, summary.world_restore_economic_tuning_lane_value_f32_text,

View file

@ -177,6 +177,10 @@ The highest-value next passes are now:
drives a derived selected-year bucket scalar in runtime restore state, and the economic-tuning drives a derived selected-year bucket scalar in runtime restore state, and the economic-tuning
mirror `[world+0x0bde]` now rebuilds from tuning lane `0` instead of freezing one stale mirror `[world+0x0bde]` now rebuilds from tuning lane `0` instead of freezing one stale
load-time word load-time word
- that same selected-year owner family now also rebuilds the direct bucket trio
`[world+0x65/+0x69/+0x6d]`, the complement trio `[world+0x71/+0x75/+0x79]`, and the scaled
companion trio `[world+0x7d/+0x81/+0x85]` from the bucket scalar instead of preserving stale
save-time residue
- the project rule on the remaining closure work is now explicit too: when one runtime-facing field - the project rule on the remaining closure work is now explicit too: when one runtime-facing field
is still ambiguous, prefer rehosting the owning source state or real reader/setter family first is still ambiguous, prefer rehosting the owning source state or real reader/setter family first
instead of guessing another derived leaf field from neighboring raw offsets instead of guessing another derived leaf field from neighboring raw offsets

View file

@ -9,12 +9,9 @@ Working rule:
## Next ## Next
- Rehost the next selected-year periodic-boundary world seam under - Rehost the next periodic-boundary world seam after the selected-year bucket family, favoring
`simulation_service_periodic_boundary_work`, extending the now-grounded selected-year bucket owner-state rebuilds that can advance shellless simulation without freezing load-time residue.
scalar into the direct bucket trio `[world+0x65/+0x69/+0x6d]` and any safe follow-on companion - Keep widening selected-year world-owner state only when a full owning reader/rebuild family is
lanes rooted in `0x00433bd0`.
- Expand the selected-year world-owner surface beyond the stepped calendar, gap scalar,
bucket-scalar, mirror, and locomotive-policy lanes when the owning reader/rebuild family is
grounded strongly enough to avoid one-off leaf guesses. grounded strongly enough to avoid one-off leaf guesses.
## In Progress ## In Progress
@ -51,6 +48,10 @@ Working rule:
and runtime restore state now derives both the selected-year bucket scalar and the and runtime restore state now derives both the selected-year bucket scalar and the
`[world+0x0bde]` economic-tuning mirror from owner-family inputs instead of preserving stale `[world+0x0bde]` economic-tuning mirror from owner-family inputs instead of preserving stale
load-time residue. load-time residue.
- That same selected-year owner family now also rebuilds the direct bucket trio
`[world+0x65/+0x69/+0x6d]`, the complement trio `[world+0x71/+0x75/+0x79]`, and the scaled
companion trio `[world+0x7d/+0x81/+0x85]` from the checked-in `0x00433bd0` artifact instead of
preserving stale save-time residue.
- Company cash, confiscation, and major governance effects now write through owner state instead of - Company cash, confiscation, and major governance effects now write through owner state instead of
drifting from market/cache readers. drifting from market/cache readers.
- Company credit rating, prime rate, book value per share, investor confidence, and management - Company credit rating, prime rate, book value per share, investor confidence, and management

View file

@ -223,7 +223,10 @@ the fixed world block, so the `All Steam/Diesel/Electric Locos Avail.` descripto
through owner state instead of living only as mirrored world flags. The selected-year seam now through owner state instead of living only as mirrored world flags. The selected-year seam now
follows the same owner rule: the checked-in `0x00433bd0` year ladder now drives a derived follows the same owner rule: the checked-in `0x00433bd0` year ladder now drives a derived
selected-year bucket scalar in runtime restore state, and the economic-tuning mirror `[world+0x0bde]` selected-year bucket scalar in runtime restore state, and the economic-tuning mirror `[world+0x0bde]`
now rebuilds from tuning lane `0` instead of freezing one stale load-time word. The same owned company annual-finance state now rebuilds from tuning lane `0` instead of freezing one stale load-time word. That same
checked-in owner family now also rebuilds the direct bucket trio `[world+0x65/+0x69/+0x6d]`, the
complement trio `[world+0x71/+0x75/+0x79]`, and the scaled companion trio `[world+0x7d/+0x81/+0x85]`
from the bucket scalar instead of preserving stale save-time residue. The same owned company annual-finance state
now also drives a shared company market reader seam for stock-capital, salary, bonus, and the full now also drives a shared company market reader seam for stock-capital, salary, bonus, and the full
two-word current/prior issue-calendar tuples, which is a better base for shellless finance two-word current/prior issue-calendar tuples, which is a better base for shellless finance
simulation than summary-only helpers. That same owned annual-finance state now also derives elapsed simulation than summary-only helpers. That same owned annual-finance state now also derives elapsed

View file

@ -10,6 +10,18 @@ IMAGE_BASE = 0x400000
PAIRED_YEAR_VALUE_TABLE_VA = 0x005F3980 PAIRED_YEAR_VALUE_TABLE_VA = 0x005F3980
PAIR_COUNT = 21 PAIR_COUNT = 21
TERMINAL_SCALAR_VA = 0x005F3A24 TERMINAL_SCALAR_VA = 0x005F3A24
DIRECT_MULTIPLIER_VAS = [0x005C8888, 0x005C9ED8, 0x005C8680]
COMPLEMENT_DIVISOR_VA = 0x005C8A20
COMPLEMENT_MULTIPLIER_VA = 0x005C8DA8
COMPLEMENT_BIAS_VA = 0x005C8618
COMPLEMENT_SCALE_VA = 0x005C9ED0
COMPLEMENT_FLOOR_VA = 0x005C88A0
COMPLEMENT_BUILD_106_MULTIPLIER_VA = 0x005C8878
COMPLEMENT_CAP_VA = 0x005C8988
SCALED_COMPANION_NUMERATOR_VA = 0x005C8A20
SCALED_COMPANION_MULTIPLIER_VA = 0x005C8680
SCALED_COMPANION_BIAS_VA = 0x005C88C8
SCALED_COMPANION_SCALE_VA = 0x005C9EC8
def read_u32_table(blob: bytes, va: int, count: int) -> list[int]: def read_u32_table(blob: bytes, va: int, count: int) -> list[int]:
@ -20,6 +32,14 @@ def read_u32_table(blob: bytes, va: int, count: int) -> list[int]:
return [struct.unpack("<I", data[i : i + 4])[0] for i in range(0, len(data), 4)] return [struct.unpack("<I", data[i : i + 4])[0] for i in range(0, len(data), 4)]
def read_f64(blob: bytes, va: int) -> float:
offset = va - IMAGE_BASE
data = blob[offset : offset + 8]
if len(data) != 8:
raise ValueError(f"f64 at {va:#x} truncated")
return struct.unpack("<d", data)[0]
def build_artifact(exe_bytes: bytes) -> dict[str, object]: def build_artifact(exe_bytes: bytes) -> dict[str, object]:
raw_pairs = read_u32_table(exe_bytes, PAIRED_YEAR_VALUE_TABLE_VA, PAIR_COUNT * 2) raw_pairs = read_u32_table(exe_bytes, PAIRED_YEAR_VALUE_TABLE_VA, PAIR_COUNT * 2)
terminal_scalar_raw = read_u32_table(exe_bytes, TERMINAL_SCALAR_VA, 1)[0] terminal_scalar_raw = read_u32_table(exe_bytes, TERMINAL_SCALAR_VA, 1)[0]
@ -33,6 +53,24 @@ def build_artifact(exe_bytes: bytes) -> dict[str, object]:
"pair_count": PAIR_COUNT, "pair_count": PAIR_COUNT,
"terminal_scalar_virtual_address": f"0x{TERMINAL_SCALAR_VA:08x}", "terminal_scalar_virtual_address": f"0x{TERMINAL_SCALAR_VA:08x}",
"terminal_scalar_value": float(terminal_scalar_raw), "terminal_scalar_value": float(terminal_scalar_raw),
"direct_lane_multipliers": [
read_f64(exe_bytes, va) for va in DIRECT_MULTIPLIER_VAS
],
"complement_formula": {
"divisor": read_f64(exe_bytes, COMPLEMENT_DIVISOR_VA),
"multiplier": read_f64(exe_bytes, COMPLEMENT_MULTIPLIER_VA),
"bias": read_f64(exe_bytes, COMPLEMENT_BIAS_VA),
"scale": read_f64(exe_bytes, COMPLEMENT_SCALE_VA),
"floor": read_f64(exe_bytes, COMPLEMENT_FLOOR_VA),
"build_106_multiplier": read_f64(exe_bytes, COMPLEMENT_BUILD_106_MULTIPLIER_VA),
"cap": read_f64(exe_bytes, COMPLEMENT_CAP_VA),
},
"scaled_companion_formula": {
"numerator": read_f64(exe_bytes, SCALED_COMPANION_NUMERATOR_VA),
"multiplier": read_f64(exe_bytes, SCALED_COMPANION_MULTIPLIER_VA),
"bias": read_f64(exe_bytes, SCALED_COMPANION_BIAS_VA),
"scale": read_f64(exe_bytes, SCALED_COMPANION_SCALE_VA),
},
"entries": entries, "entries": entries,
} }