Extend atlas seam annotations across load/save and transport
This commit is contained in:
parent
97295d4060
commit
7b44279d7e
7 changed files with 1450 additions and 330 deletions
|
|
@ -4,16 +4,16 @@
|
|||
`shell_active_mode_run_profile_startup_and_load_dispatch` at `0x00438890`, the shell-mode
|
||||
switcher `shell_transition_mode` at `0x00482ec0`, the first grounded world-entry branch
|
||||
`world_entry_transition_and_runtime_bringup` at `0x00443a50`,
|
||||
`shell_map_file_world_bundle_coordinator` at `0x00445de0`, reference-database setup via
|
||||
`map_bundle_open_reference_databases` at `0x00444dd0`, and narrower loaders such as
|
||||
`map_load_geographic_label_database` and `map_load_city_database`.
|
||||
`shell_map_file_world_bundle_coordinator` at `0x00445de0`, early reference-package save via
|
||||
`map_bundle_open_reference_package_and_serialize_early_world_datasets` at `0x00444dd0`, and narrower tagged collection owners such as
|
||||
`geographic_label_database_refresh_records_from_tagged_bundle` and `city_database_entry_collection_refresh_records_from_tagged_bundle`.
|
||||
- Trigger/Cadence: shell tutorial launch, editor or detail-panel file actions through `fileopt.win`,
|
||||
map-scenario open paths, and scenario-text export batch commands.
|
||||
- Key Dispatchers: `shell_map_file_entry_coordinator`,
|
||||
`shell_active_mode_run_profile_startup_and_load_dispatch`, `shell_transition_mode`,
|
||||
`world_entry_transition_and_runtime_bringup`, `world_runtime_release_global_services`, `shell_map_file_world_bundle_coordinator`,
|
||||
`map_bundle_open_reference_databases`, `map_load_geographic_label_database`,
|
||||
`map_load_city_database`, `scenario_text_export_build_language_file`,
|
||||
`map_bundle_open_reference_package_and_serialize_early_world_datasets`, `geographic_label_database_refresh_records_from_tagged_bundle`,
|
||||
`city_database_entry_collection_refresh_records_from_tagged_bundle`, `scenario_text_export_build_language_file`,
|
||||
`scenario_text_export_report_language_file`, `scenario_text_export_batch_process_maps`.
|
||||
- State Anchors: shell-side file staging buffers at `0x0062bee0` and `0x0062bec4`, shell and mode
|
||||
globals at `0x006cec74` and `0x006cec78`, world object root `0x0062c120`, map bundle state
|
||||
|
|
@ -37,7 +37,31 @@
|
|||
mode `11` is tighter now too: it still maps to `.gmt`, but instead of looking like another
|
||||
gameplay save family it conditionally diverts into the same `.gmt` preview-surface pipeline owned
|
||||
by the Multiplayer preview dataset object at `0x006cd8d8`, and only falls back to the normal
|
||||
reference-bundle path when that dataset object is absent. The shell-side mode owner above those
|
||||
reference-bundle path when that dataset object is absent. That fallback owner is tighter now too:
|
||||
`0x00444dd0` is not a generic database opener, but the early package-save prelude that seeds the
|
||||
shared stage/progress globals, opens one `0x30d40` bundle through `0x00530c80`, handles the
|
||||
localized failure modal `0x0fda`, and then serializes the first direct package band in a fixed
|
||||
order: chunks `0x32c8/0x32c9`, direct saves of `[world+0x66be]`, `[world+0x66b2]`, and
|
||||
`[world+0x66b6]`, chunk `0x32dc`, the staged `0x108` profile block under `0x3714/0x3715`, then
|
||||
`world_serialize_runtime_grid_and_secondary_raster_tables_into_bundle` `0x00449520` for the
|
||||
early world-grid and sidecar-table band, then
|
||||
`aux_candidate_collection_serialize_records_into_bundle_payload` `0x00416a70` for the direct
|
||||
`0x0062b2fc` source-or-auxiliary record family, and only after that the neighboring reference
|
||||
and manager families before `shell_map_file_world_bundle_coordinator` continues with the later
|
||||
tagged collections. That `0x0062b2fc` seam is tighter now too: `0x00416a70` first builds one
|
||||
temporary scored queue from each record's linked chain at `[entry+0x04]`, writes one leading
|
||||
`0xbabe` header, and then serializes the fixed fields, counted dword runs, optional byte payload,
|
||||
paired one-byte bands, and trailing dword for each queued record; the load-side companion is
|
||||
`aux_candidate_collection_construct_stream_load_records_and_refresh_runtime_followons`
|
||||
`0x004196c0`, which now clearly tails into
|
||||
`aux_candidate_collection_rebank_or_clone_records_by_availability_pass_and_refresh_owner_links`
|
||||
`0x00419230` before the later world-load side continues, with destructor
|
||||
`aux_candidate_collection_release_templates_queues_and_indexed_storage` `0x00419680`. The fixed
|
||||
tail is explicit now too: `0x00444dd0` writes one direct dword from
|
||||
`[world+0x19]`, one zeroed `0x1f4`-byte slab under `0x32cf`, closes the package, derives the
|
||||
preview path through `0x00442740`, and then conditionally emits the companion-image and
|
||||
companion-payload sidecars through `0x00441f70` and `0x00442900` when `[world+0x66c8]` and
|
||||
`[world+0x66c9]` are set. The shell-side mode owner above those
|
||||
file coordinators is clearer now too. `shell_transition_mode` no longer reads like a generic mode
|
||||
switch: its ABI is now grounded as a `thiscall` with two stack arguments because the body reads
|
||||
the requested mode from `[esp+0x0c]` and returns with `ret 8`. The grounded world-entry
|
||||
|
|
@ -52,6 +76,49 @@
|
|||
`0x0062b2fc`, `0x0062b268`, `0x006cea4c`, and `0x006acd34` in that order before it drains the
|
||||
shell-helper handle band `[world+0x46a80..+0x46aa0]`, the variable owner band `[world+0x46aa4]`,
|
||||
and the linked chains at `[world+0x66a6]` and `[world+0x66aa]`.
|
||||
The corresponding world-load allocation branch is tighter now too: inside `0x00438c70`,
|
||||
`0x0062b2fc` is allocated as a `0xb8`-byte object and then constructed through
|
||||
`aux_candidate_collection_construct_seed_globals_and_helper_bands_then_import_records`
|
||||
`0x0041aa50`, which seeds the collection base, resets the neighboring constructor globals, builds
|
||||
the helper bands at `[this+0x88/+0x8c/+0x90]` through `0x0041a990`, and only then tails into the
|
||||
tagged import owner `0x004196c0`. The next two roots in the same load strip are now explicit
|
||||
too: `0x0062ba8c` is allocated and constructed through
|
||||
`structure_candidate_collection_construct_and_stream_load_records_then_refresh_counts`
|
||||
`0x0041f4e0`, which enters the tagged import owner `0x0041ede0` and then refreshes the aggregate
|
||||
filter/year-visible counts through `0x0041e970`; and `0x006ada84` is allocated and constructed
|
||||
through `locomotive_collection_construct_and_stream_load_records` `0x00462520`, which enters the
|
||||
linked-era locomotive import owner `0x00461f10` and then refreshes the live availability override
|
||||
band through `0x00461e00`. The same fan-out now also has explicit constructor ownership for the
|
||||
adjacent typed roots: the live company collection `0x0062be10` is constructed through
|
||||
`company_collection_construct` `0x00429950`, the live profile/chairman collection `0x006ceb9c`
|
||||
is constructed through `profile_collection_construct` `0x00477740`, the live train collection
|
||||
`0x006cfcbc` is constructed through `train_collection_construct` `0x004b2340`, the sibling
|
||||
indexed collection `0x006acd34` is constructed through
|
||||
`runtime_object_collection_construct_vtable_5cae10` `0x00455320`, the support family
|
||||
`0x0062b244` is constructed through
|
||||
`support_collection_construct_seed_counters_and_clear_large_sideband` `0x0040aeb0`, and the live
|
||||
world root `0x0062c120` is published through
|
||||
`world_runtime_construct_root_and_seed_global_0x62c120` `0x0044cf70` before the heavier bundle
|
||||
load body continues through `0x00449200` and `0x0044cfb0`. The profile-side tagged header
|
||||
siblings are explicit too: runtime load re-enters
|
||||
`profile_collection_refresh_tagged_header_counts_from_bundle` `0x00477780`, while package save
|
||||
later mirrors the same `0x5209/0x520a/0x520b` trio back out through
|
||||
`profile_collection_serialize_tagged_header_counts_into_bundle` `0x004777e0`. The same tagged
|
||||
symmetry is now bounded for the live company collection too: world-load refresh re-enters
|
||||
`company_collection_load_tagged_header_counts_and_refresh_live_records_from_bundle` `0x00429af0`,
|
||||
while the package-save path mirrors the same `0x61a9/0x61aa/0x61ab` bracket through
|
||||
`company_collection_serialize_tagged_header_counts_and_save_live_records_into_bundle`
|
||||
`0x00429b90`, whose per-company callback is currently the no-op stub `0x00424000` while the
|
||||
load-side per-company follow-on is `company_refresh_post_load_year_clamp_and_runtime_support_fields`
|
||||
`0x004268e0`. The same tagged symmetry is now bounded for the live train collection too:
|
||||
world-load refresh re-enters
|
||||
`train_collection_load_tagged_header_counts_and_refresh_live_records_from_bundle` `0x004b2700`,
|
||||
while the package-save path mirrors the same `0x5209/0x520a/0x520b` header bracket and per-train
|
||||
record walk through
|
||||
`train_collection_serialize_tagged_header_counts_and_save_live_records_into_bundle`
|
||||
`0x004b27a0`; the per-train payload seam itself is now explicit too, with route-list load through
|
||||
`train_refresh_tagged_route_list_payload_from_bundle` `0x004a84b0` and route-list save through
|
||||
`train_serialize_tagged_route_list_payload_into_bundle` `0x004a7030`.
|
||||
The later world-entry reactivation branch correspondingly uses `(1, esi)` rather than `(1, 0)`.
|
||||
The current live hook probes now push the remaining auto-load gap much later too: on the
|
||||
hook-driven path `shell_transition_mode(4, 0)` returns cleanly, and the full old-mode teardown
|
||||
|
|
@ -89,30 +156,25 @@
|
|||
ready-count log so the mode-`4` startup lane either stages immediately or shows exactly how far
|
||||
the gate gets. That adjustment worked on the next run: the hook now stages and completes the
|
||||
`shell_transition_mode` path again, with `LoadScreen.win` construction and publish returning
|
||||
cleanly. But the post-publish startup subchain is still unresolved: there is still no trusted
|
||||
`0x46c40` allocator hit, no direct `0x004336d0` entry, and no direct `0x00438890` entry. So
|
||||
the next clean runtime boundary is the tiny `LoadScreen.win` scalar setter at `0x004ea710`,
|
||||
which sits immediately before the `0x0053b070` allocation in the static mode-`4` branch. The
|
||||
immediate next runtime check is even more concrete than the helper hook, though: inspect the
|
||||
state that `0x004ea710` should leave behind. The hook now logs the post-transition
|
||||
`LoadScreen.win` singleton, its field `[+0x78]`, `0x006cec78`, the shell state's `[+0x0c]`
|
||||
active-mode object field, and the startup selector. If `0x004ea710` really ran on the mode-`4`
|
||||
branch, `[LoadScreen.win+0x78]` should no longer be zero after `shell_transition_mode` returns.
|
||||
The latest run answered that directly: after transition return, `field_active_mode_object` is
|
||||
still the `LoadScreen.win` singleton, `0x006cec78` is still null, `[LoadScreen.win+0x78]` is
|
||||
still zero, and the startup selector is still `3`. So the current best read is that RT3 is
|
||||
still parked in the plain `LoadScreen.win` state at transition return rather than having entered
|
||||
the separate runtime-object path yet. That shifts the best next runtime boundary from “deeper
|
||||
inside `shell_transition_mode`” to “what later active-mode service tick, if any, promotes the
|
||||
load-screen object into the startup-dispatch path.” The next run now logs the first few
|
||||
shell-state service ticks after auto-load is attempted with that same state tuple
|
||||
(`0x006cec78`, `[shell_state+0x0c]`, `0x006d10b0`, `[LoadScreen.win+0x78]`, selector), so the
|
||||
next question is very narrow: does one later service tick finally promote the plain
|
||||
`LoadScreen.win` state into the startup-runtime object path, or does it stay frozen as-is? The
|
||||
internal selector split in `0x438890` is tighter now too: `[0x006cec7c+0x01]` is a separate
|
||||
seven-way startup selector, not the shell mode id. Values `1` and `7` load `Tutorial_2.gmp` and
|
||||
`Tutorial_1.gmp`, values `3/5/6` collapse into the same profile-seeded file-load lane through
|
||||
`0x445ac0([0x006cec7c]+0x11, 4, &out_success)`, value `2` is a world-root initialization lane
|
||||
cleanly. The post-publish startup subchain is no longer unresolved on the static side, though.
|
||||
Direct disassembly of the mode-`4` branch at `0x0048302a..0x004830ca` now closes it completely:
|
||||
after constructing `LoadScreen.win`, the branch sets shell state `[transition+0x08] = 4`,
|
||||
chooses one page scalar `110.0f`, `236.0f`, or `5.0f`, writes that page id through
|
||||
`shell_load_screen_window_set_active_page` `0x004ea710`, allocates one `0x46c40`-byte runtime
|
||||
object through `0x0053b070`, resets it through
|
||||
`world_runtime_reset_startup_dispatch_state_bands` `0x004336d0`, stores the result into
|
||||
`0x006cec78`, and then directly enters
|
||||
`shell_active_mode_run_profile_startup_and_load_dispatch` `0x00438890` as `(1, 0)` before
|
||||
publishing the active-mode object back through `0x005389c0`. So the static startup chain after
|
||||
`LoadScreen.win` publish is now explicit rather than inferred from the earlier hook traces. The
|
||||
remaining runtime-side question is narrower: why the earlier hook snapshots still showed
|
||||
`[LoadScreen.win+0x78] == 0` and `0x006cec78 == 0` immediately after transition return even
|
||||
though the static mode-`4` branch does not leave those fields that way once it reaches the
|
||||
startup-dispatch path. The internal selector split in `0x438890` is tighter now too:
|
||||
`[0x006cec7c+0x01]` is a separate seven-way startup selector, not the shell mode id. Values `1`
|
||||
and `7` load `Tutorial_2.gmp` and `Tutorial_1.gmp`, values `3/5/6` collapse into the same
|
||||
profile-seeded file-load lane through `0x445ac0([0x006cec7c]+0x11, 4, &out_success)`, value `2`
|
||||
is a world-root initialization lane
|
||||
that allocates `0x0062c120` and then forces selector `3`, and value `4` is the setup-side world
|
||||
reset or regeneration lane that rebuilds `0x0062c120` from `0x006d14cc/0x006d14d0` before later
|
||||
world setup continues. The write side is tighter now too: `Campaign.win` writes selector `6`,
|
||||
|
|
@ -346,11 +408,14 @@
|
|||
sixteen-byte per-scenario campaign selector or unlock band consumed directly by `Campaign.win`.
|
||||
The neighboring profile helpers are tighter now too: `0x0047bbf0` is the broad default reset for
|
||||
the staged `0x108`-byte runtime-profile record, clearing the whole record and then reseeding the
|
||||
visible setup and campaign anchors `[profile+0x77]`, `[profile+0x79]`, `[profile+0x7d]`,
|
||||
`[profile+0x83]`, `[profile+0x87]`, and `[profile+0x97]`; and `0x0047bc50` is the compact scan
|
||||
helper over `[profile+0xc6..+0xd5]` that returns the first selector byte below `2`, which keeps
|
||||
that band tied to staged campaign progress or unlock state rather than to the earlier setup-panel
|
||||
payload fields.
|
||||
visible setup and campaign anchors `[profile+0x77]`, `[profile+0x79]`, `[profile+0x7d]`, the
|
||||
random-like dword `[profile+0x83]`, the first setup row-marker byte `[profile+0x87]`, and the
|
||||
file-backed launch or rehydrate latch `[profile+0x97]`; `0x00502c00` is now tighter on the same
|
||||
slab because its file-backed lane copies the selected row's primary and secondary `0x32`-byte
|
||||
string bands into `[profile+0x11]` and `[profile+0x44]` while arming presence byte
|
||||
`[profile+0x10]`; and `0x0047bc50` is the compact scan helper over `[profile+0xc6..+0xd5]` that
|
||||
returns the first selector byte below `2`, which keeps that band tied to staged campaign progress
|
||||
or unlock state rather than to the earlier setup-panel payload fields.
|
||||
The message-dispatch side is tighter now too. The local classifier at `0x004b91d8` routes the
|
||||
control range `0x0c352..0x0c39b` through five concrete case classes: `0x0c352..0x0c361` enter
|
||||
the shared selector or launch branch, `0x0c362..0x0c367` force local page `1`,
|
||||
|
|
@ -441,10 +506,12 @@
|
|||
`.gmp`, `.gmx`, `.gmc`, `.gms`, `.gmt`, `.smp`, `Quicksave`, the `0x004dd010` mode table at
|
||||
`0x005f3d58`, the auxiliary-owner presence check at `0x00434050`, and the `.gmt` handoff through
|
||||
`0x00469d30`, together with localized string evidence from ids `3018` and `3898`.
|
||||
- Direct shell stubs above that coordinator are tighter now too: `0x004408b0` is the pure
|
||||
zero-flag wrapper into `shell_map_file_world_bundle_coordinator`, while `0x004408d0` is the
|
||||
sibling wrapper with flag triplet `(0, 1, 0)`. The exact user-facing command names for those two
|
||||
wrappers are still open, but the dispatcher shape is no longer.
|
||||
- Direct shell stubs above that coordinator are tighter now too: `0x004408b0` is the ordinary
|
||||
`Save game` wrapper and forwards the pure zero-flag triplet into
|
||||
`shell_map_file_world_bundle_coordinator`; `0x004408d0` is the sibling `Quick save` wrapper,
|
||||
forwarding flag triplet `(0, 1, 0)`. RT3.lng closes the neighboring `shell_map_file_entry_coordinator`
|
||||
pair in the same way: `0x00441ac0` is `Load game` and `0x00441af0` is `Quick load`, with the
|
||||
same `(0, 0, 0)` versus `(0, 1, 0)` split above `0x00445ac0`.
|
||||
- Open Questions: bit `0x1` on both broad coordinators now grounds the Quicksave name seed and the
|
||||
former third `fileopt.win` flag has been ruled out as a file-flow question because it just opens
|
||||
`SettingsWindow.win`. The old broad extension question is mostly resolved: `.gmp` is the
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue