Widen save-native company stat-band windows
This commit is contained in:
parent
9ff4cac6fb
commit
f52df7d233
4 changed files with 66 additions and 147 deletions
|
|
@ -56,7 +56,9 @@ and it now also carries the first grounded stat-band root windows at `[company+0
|
|||
build on owned state instead of another round of single-field save-offset guesses. The first
|
||||
runtime-side `0x2329` stat-family reader seam is now rehosted too for the currently grounded slots
|
||||
`0x0d` (`current_cash`) and `0x1d` (`book_value_per_share`), so later annual-finance logic can
|
||||
extend one shared reader family instead of hard-coding more direct field accesses. A checked-in
|
||||
extend one shared reader family instead of hard-coding more direct field accesses. Those saved
|
||||
stat-band windows are now widened to 16 dwords per root in save-slice/runtime state so later
|
||||
year-series finance closure has enough owned raw state to attach to. A checked-in
|
||||
The working rule on the remaining frontier is explicit now too: when a lane is still ambiguous, we
|
||||
should prefer rehosting the owning source state or the real reader/setter family rather than
|
||||
guessing one more derived leaf field from nearby offsets. A checked-in
|
||||
|
|
|
|||
|
|
@ -3070,27 +3070,27 @@ pub fn inspect_save_company_and_chairman_analysis_bytes(
|
|||
build_save_dword_candidate(&bytes, record_offset, label, *relative_offset)
|
||||
})
|
||||
.collect::<Option<Vec<_>>>()?;
|
||||
let stat_band_root_0cfb_candidates =
|
||||
SAVE_COMPANY_RECORD_STAT_BAND_ROOT_0CFB_CANDIDATE_FIELDS
|
||||
.iter()
|
||||
.map(|(label, relative_offset)| {
|
||||
build_save_dword_candidate(&bytes, record_offset, label, *relative_offset)
|
||||
})
|
||||
.collect::<Option<Vec<_>>>()?;
|
||||
let stat_band_root_0d7f_candidates =
|
||||
SAVE_COMPANY_RECORD_STAT_BAND_ROOT_0D7F_CANDIDATE_FIELDS
|
||||
.iter()
|
||||
.map(|(label, relative_offset)| {
|
||||
build_save_dword_candidate(&bytes, record_offset, label, *relative_offset)
|
||||
})
|
||||
.collect::<Option<Vec<_>>>()?;
|
||||
let stat_band_root_1c47_candidates =
|
||||
SAVE_COMPANY_RECORD_STAT_BAND_ROOT_1C47_CANDIDATE_FIELDS
|
||||
.iter()
|
||||
.map(|(label, relative_offset)| {
|
||||
build_save_dword_candidate(&bytes, record_offset, label, *relative_offset)
|
||||
})
|
||||
.collect::<Option<Vec<_>>>()?;
|
||||
let stat_band_root_0cfb_candidates = build_save_company_stat_band_candidates(
|
||||
&bytes,
|
||||
record_offset,
|
||||
SAVE_COMPANY_RECORD_STAT_BAND_ROOT_0CFB_OFFSET,
|
||||
"stat_band_0cfb",
|
||||
SAVE_COMPANY_RECORD_STAT_BAND_ROOT_WINDOW_LEN_DWORDS,
|
||||
)?;
|
||||
let stat_band_root_0d7f_candidates = build_save_company_stat_band_candidates(
|
||||
&bytes,
|
||||
record_offset,
|
||||
SAVE_COMPANY_RECORD_STAT_BAND_ROOT_0D7F_OFFSET,
|
||||
"stat_band_0d7f",
|
||||
SAVE_COMPANY_RECORD_STAT_BAND_ROOT_WINDOW_LEN_DWORDS,
|
||||
)?;
|
||||
let stat_band_root_1c47_candidates = build_save_company_stat_band_candidates(
|
||||
&bytes,
|
||||
record_offset,
|
||||
SAVE_COMPANY_RECORD_STAT_BAND_ROOT_1C47_OFFSET,
|
||||
"stat_band_1c47",
|
||||
SAVE_COMPANY_RECORD_STAT_BAND_ROOT_WINDOW_LEN_DWORDS,
|
||||
)?;
|
||||
entries.push(SmpSaveCompanyRecordAnalysisEntry {
|
||||
company_id,
|
||||
name,
|
||||
|
|
@ -3498,6 +3498,7 @@ const SAVE_COMPANY_RECORD_TRACK_LAYING_CAPACITY_OFFSET: usize = 0x7680;
|
|||
const SAVE_COMPANY_RECORD_STAT_BAND_ROOT_0CFB_OFFSET: usize = 0x0cfb;
|
||||
const SAVE_COMPANY_RECORD_STAT_BAND_ROOT_0D7F_OFFSET: usize = 0x0d7f;
|
||||
const SAVE_COMPANY_RECORD_STAT_BAND_ROOT_1C47_OFFSET: usize = 0x1c47;
|
||||
const SAVE_COMPANY_RECORD_STAT_BAND_ROOT_WINDOW_LEN_DWORDS: usize = 16;
|
||||
const SAVE_COMPANY_RECORD_SCALAR_CANDIDATE_FIELDS: [(&str, usize); 7] = [
|
||||
("mutable_support_scalar", 0x4f),
|
||||
("young_company_support_scalar", 0x57),
|
||||
|
|
@ -3527,108 +3528,6 @@ const SAVE_COMPANY_RECORD_POST_CAPACITY_CANDIDATE_FIELDS: [(&str, usize); 6] = [
|
|||
("post_capacity_word_5", 0x7694),
|
||||
("post_capacity_word_6", 0x7698),
|
||||
];
|
||||
const SAVE_COMPANY_RECORD_STAT_BAND_ROOT_0CFB_CANDIDATE_FIELDS: [(&str, usize); 8] = [
|
||||
(
|
||||
"stat_band_0cfb_word_1",
|
||||
SAVE_COMPANY_RECORD_STAT_BAND_ROOT_0CFB_OFFSET,
|
||||
),
|
||||
(
|
||||
"stat_band_0cfb_word_2",
|
||||
SAVE_COMPANY_RECORD_STAT_BAND_ROOT_0CFB_OFFSET + 4,
|
||||
),
|
||||
(
|
||||
"stat_band_0cfb_word_3",
|
||||
SAVE_COMPANY_RECORD_STAT_BAND_ROOT_0CFB_OFFSET + 8,
|
||||
),
|
||||
(
|
||||
"stat_band_0cfb_word_4",
|
||||
SAVE_COMPANY_RECORD_STAT_BAND_ROOT_0CFB_OFFSET + 12,
|
||||
),
|
||||
(
|
||||
"stat_band_0cfb_word_5",
|
||||
SAVE_COMPANY_RECORD_STAT_BAND_ROOT_0CFB_OFFSET + 16,
|
||||
),
|
||||
(
|
||||
"stat_band_0cfb_word_6",
|
||||
SAVE_COMPANY_RECORD_STAT_BAND_ROOT_0CFB_OFFSET + 20,
|
||||
),
|
||||
(
|
||||
"stat_band_0cfb_word_7",
|
||||
SAVE_COMPANY_RECORD_STAT_BAND_ROOT_0CFB_OFFSET + 24,
|
||||
),
|
||||
(
|
||||
"stat_band_0cfb_word_8",
|
||||
SAVE_COMPANY_RECORD_STAT_BAND_ROOT_0CFB_OFFSET + 28,
|
||||
),
|
||||
];
|
||||
const SAVE_COMPANY_RECORD_STAT_BAND_ROOT_0D7F_CANDIDATE_FIELDS: [(&str, usize); 8] = [
|
||||
(
|
||||
"stat_band_0d7f_word_1",
|
||||
SAVE_COMPANY_RECORD_STAT_BAND_ROOT_0D7F_OFFSET,
|
||||
),
|
||||
(
|
||||
"stat_band_0d7f_word_2",
|
||||
SAVE_COMPANY_RECORD_STAT_BAND_ROOT_0D7F_OFFSET + 4,
|
||||
),
|
||||
(
|
||||
"stat_band_0d7f_word_3",
|
||||
SAVE_COMPANY_RECORD_STAT_BAND_ROOT_0D7F_OFFSET + 8,
|
||||
),
|
||||
(
|
||||
"stat_band_0d7f_word_4",
|
||||
SAVE_COMPANY_RECORD_STAT_BAND_ROOT_0D7F_OFFSET + 12,
|
||||
),
|
||||
(
|
||||
"stat_band_0d7f_word_5",
|
||||
SAVE_COMPANY_RECORD_STAT_BAND_ROOT_0D7F_OFFSET + 16,
|
||||
),
|
||||
(
|
||||
"stat_band_0d7f_word_6",
|
||||
SAVE_COMPANY_RECORD_STAT_BAND_ROOT_0D7F_OFFSET + 20,
|
||||
),
|
||||
(
|
||||
"stat_band_0d7f_word_7",
|
||||
SAVE_COMPANY_RECORD_STAT_BAND_ROOT_0D7F_OFFSET + 24,
|
||||
),
|
||||
(
|
||||
"stat_band_0d7f_word_8",
|
||||
SAVE_COMPANY_RECORD_STAT_BAND_ROOT_0D7F_OFFSET + 28,
|
||||
),
|
||||
];
|
||||
const SAVE_COMPANY_RECORD_STAT_BAND_ROOT_1C47_CANDIDATE_FIELDS: [(&str, usize); 8] = [
|
||||
(
|
||||
"stat_band_1c47_word_1",
|
||||
SAVE_COMPANY_RECORD_STAT_BAND_ROOT_1C47_OFFSET,
|
||||
),
|
||||
(
|
||||
"stat_band_1c47_word_2",
|
||||
SAVE_COMPANY_RECORD_STAT_BAND_ROOT_1C47_OFFSET + 4,
|
||||
),
|
||||
(
|
||||
"stat_band_1c47_word_3",
|
||||
SAVE_COMPANY_RECORD_STAT_BAND_ROOT_1C47_OFFSET + 8,
|
||||
),
|
||||
(
|
||||
"stat_band_1c47_word_4",
|
||||
SAVE_COMPANY_RECORD_STAT_BAND_ROOT_1C47_OFFSET + 12,
|
||||
),
|
||||
(
|
||||
"stat_band_1c47_word_5",
|
||||
SAVE_COMPANY_RECORD_STAT_BAND_ROOT_1C47_OFFSET + 16,
|
||||
),
|
||||
(
|
||||
"stat_band_1c47_word_6",
|
||||
SAVE_COMPANY_RECORD_STAT_BAND_ROOT_1C47_OFFSET + 20,
|
||||
),
|
||||
(
|
||||
"stat_band_1c47_word_7",
|
||||
SAVE_COMPANY_RECORD_STAT_BAND_ROOT_1C47_OFFSET + 24,
|
||||
),
|
||||
(
|
||||
"stat_band_1c47_word_8",
|
||||
SAVE_COMPANY_RECORD_STAT_BAND_ROOT_1C47_OFFSET + 28,
|
||||
),
|
||||
];
|
||||
const SAVE_COMPANY_RECORD_START_SCAN_LIMIT: usize = 0x120;
|
||||
|
||||
const SAVE_CHAIRMAN_RECORD_NAME_OFFSET: usize = 0x08;
|
||||
|
|
@ -3754,27 +3653,27 @@ fn parse_save_company_roster_probe(
|
|||
bytes,
|
||||
record_offset + SAVE_COMPANY_RECORD_TAKEOVER_COOLDOWN_OFFSET,
|
||||
)?;
|
||||
let stat_band_root_0cfb_candidates =
|
||||
SAVE_COMPANY_RECORD_STAT_BAND_ROOT_0CFB_CANDIDATE_FIELDS
|
||||
.iter()
|
||||
.map(|(label, relative_offset)| {
|
||||
build_save_dword_candidate(bytes, record_offset, label, *relative_offset)
|
||||
})
|
||||
.collect::<Option<Vec<_>>>()?;
|
||||
let stat_band_root_0d7f_candidates =
|
||||
SAVE_COMPANY_RECORD_STAT_BAND_ROOT_0D7F_CANDIDATE_FIELDS
|
||||
.iter()
|
||||
.map(|(label, relative_offset)| {
|
||||
build_save_dword_candidate(bytes, record_offset, label, *relative_offset)
|
||||
})
|
||||
.collect::<Option<Vec<_>>>()?;
|
||||
let stat_band_root_1c47_candidates =
|
||||
SAVE_COMPANY_RECORD_STAT_BAND_ROOT_1C47_CANDIDATE_FIELDS
|
||||
.iter()
|
||||
.map(|(label, relative_offset)| {
|
||||
build_save_dword_candidate(bytes, record_offset, label, *relative_offset)
|
||||
})
|
||||
.collect::<Option<Vec<_>>>()?;
|
||||
let stat_band_root_0cfb_candidates = build_save_company_stat_band_candidates(
|
||||
bytes,
|
||||
record_offset,
|
||||
SAVE_COMPANY_RECORD_STAT_BAND_ROOT_0CFB_OFFSET,
|
||||
"stat_band_0cfb",
|
||||
SAVE_COMPANY_RECORD_STAT_BAND_ROOT_WINDOW_LEN_DWORDS,
|
||||
)?;
|
||||
let stat_band_root_0d7f_candidates = build_save_company_stat_band_candidates(
|
||||
bytes,
|
||||
record_offset,
|
||||
SAVE_COMPANY_RECORD_STAT_BAND_ROOT_0D7F_OFFSET,
|
||||
"stat_band_0d7f",
|
||||
SAVE_COMPANY_RECORD_STAT_BAND_ROOT_WINDOW_LEN_DWORDS,
|
||||
)?;
|
||||
let stat_band_root_1c47_candidates = build_save_company_stat_band_candidates(
|
||||
bytes,
|
||||
record_offset,
|
||||
SAVE_COMPANY_RECORD_STAT_BAND_ROOT_1C47_OFFSET,
|
||||
"stat_band_1c47",
|
||||
SAVE_COMPANY_RECORD_STAT_BAND_ROOT_WINDOW_LEN_DWORDS,
|
||||
)?;
|
||||
entries.push(SmpLoadedCompanyRosterEntry {
|
||||
company_id,
|
||||
active,
|
||||
|
|
@ -3848,6 +3747,22 @@ fn runtime_company_stat_band_candidate_from_save(
|
|||
}
|
||||
}
|
||||
|
||||
fn build_save_company_stat_band_candidates(
|
||||
bytes: &[u8],
|
||||
record_offset: usize,
|
||||
root_offset: usize,
|
||||
label_prefix: &str,
|
||||
word_count: usize,
|
||||
) -> Option<Vec<SmpSaveDwordCandidate>> {
|
||||
(0..word_count)
|
||||
.map(|index| {
|
||||
let relative_offset = root_offset.checked_add(index.checked_mul(4)?)?;
|
||||
let label = format!("{label_prefix}_word_{}", index + 1);
|
||||
build_save_dword_candidate(bytes, record_offset, &label, relative_offset)
|
||||
})
|
||||
.collect::<Option<Vec<_>>>()
|
||||
}
|
||||
|
||||
fn detect_save_company_record_start_offset(
|
||||
bytes: &[u8],
|
||||
header_probe: &SmpSaveTaggedCollectionHeaderProbe,
|
||||
|
|
|
|||
|
|
@ -116,7 +116,8 @@ The highest-value next passes are now:
|
|||
latches, and the first grounded stat-band root windows at `[company+0x0cfb]`, `[company+0x0d7f]`,
|
||||
and `[company+0x1c47]` for each live company, so later finance/stat-family readers can attach to
|
||||
owned runtime data instead of one more guessed save offset; the first runtime-side `0x2329`
|
||||
stat-family reader seam is now also rehosted for slots `0x0d` and `0x1d`
|
||||
stat-family reader seam is now also rehosted for slots `0x0d` and `0x1d`, and the saved
|
||||
stat-band windows themselves now carry 16 dwords per root
|
||||
- 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
|
||||
instead of guessing another derived leaf field from neighboring raw offsets
|
||||
|
|
|
|||
|
|
@ -201,7 +201,8 @@ roster. The current owned company-side roster now includes not just the market/c
|
|||
the first grounded stat-band root windows at `[company+0x0cfb]`, `[company+0x0d7f]`, and
|
||||
`[company+0x1c47]`, and the first runtime-side `0x2329` stat-family reader seam is now rehosted
|
||||
for slots `0x0d` and `0x1d`, so later finance readers can target saved owner state and one shared
|
||||
reader family directly.
|
||||
reader family directly. Those stat-band windows now carry 16 dwords per root in the save-slice and
|
||||
runtime-owned company market state.
|
||||
|
||||
## Why This Boundary
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue