1776 lines
154 KiB
Markdown
1776 lines
154 KiB
Markdown
# Input, Save/Load, and Simulation: Post-load Generation, PaintTerrain, and Save/Load Restore
|
|
|
|
### Post-load Generation, PaintTerrain, and Save/Load Restore
|
|
|
|
The same brush strip is tighter now too:
|
|
`0x004bc210` stores the selected ordinal and refreshes one scalar caption
|
|
from table `0x00621e24`, `0x004bc260` exposes the cached world coordinate pair plus the
|
|
currently selected scalar, and `0x004bc290` restyles the ordinal strip `0x0fa1..0x0fa7` plus
|
|
the mapped mode strip `0x0faa..0x0faf` against the current mode dword `[0x006d0818+0x8c]`. The
|
|
next unresolved layer is narrower and more semantic: the setup side now has one grounded
|
|
owner, `world_run_post_load_generation_pipeline`, and its building-side branch is no longer just
|
|
one opaque block. We now have a region family, a region-border overlay rebuild, a region-owned
|
|
structure-demand and placement dispatcher, and a deeper per-region worker that computes category
|
|
demand, subtracts existing coverage, and tries candidate placements. The category map is tighter
|
|
too: category `0` falls back to `House`, category `2` is the year-gated weighted region-profile
|
|
family that also feeds the localized `Industry Weightings` stats panel, and category `3` now
|
|
reaches a separate pool-driven picker whose fallback label is `Commercial` but whose aligned
|
|
player-facing stats bucket is `City Support`. The normalized region band is tighter too:
|
|
`world_region_normalize_cached_structure_balance_scalars` `0x00422320` no longer just writes an
|
|
anonymous cached preview band at `[region+0x2e2/+0x2e6/+0x2ea/+0x2ee]`. Current growth-report
|
|
evidence now grounds `[region+0x2e2]` as the weighted-profit-margin scalar and `[region+0x2ee]`
|
|
as the annual-density-adjust scalar later formatted as a percent in `Stats - City/Region`, with
|
|
`[region+0x2e6/+0x2ea]` left as the intermediate normalized-delta and clamped companion slots
|
|
beneath that final adjust term. The per-region prepass feeding that normalization is tighter too:
|
|
`0x00420d40` clears `[region+0x306/+0x30a/+0x30e]`, walks the linked placed-structure chain from
|
|
`[region+0x383]`, accumulates two local placed-structure metrics through `0x0040ca70` and
|
|
`0x0040ca80`, and only for class-0 candidates also folds source field `[source+0x141]` through
|
|
`0x0040cec0` into the third accumulator before tailing into the later scalar refresh. That tail
|
|
helper `0x00420560` is tighter now too: on class-0 regions it revisits the same linked chain and
|
|
folds a class-mix contribution into `[region+0x312]`, with one source-derived term for candidate
|
|
class `0`, a separate branch keyed by `[candidate+0x78c]` and `[site+0x246]` for class `2`, one
|
|
fixed increment for class `3`, and no current contribution from class `1`. One neighboring
|
|
collection-side dispatcher is tighter now too: `0x00433b80` only runs when global mutation depth
|
|
`0x0062be40` is back at zero and then conditionally fans into the optional refresh hooks
|
|
`0x00481430`, `0x00413860`, `0x004b2a90`, and
|
|
`route_entry_collection_run_optional_refresh_hooks_and_validate_world_cell_side_lists`
|
|
`0x004931e0`. The periodic boundary
|
|
side is narrower now too. `0x00422100`, reached only from
|
|
`simulation_service_periodic_boundary_work` `0x0040a590`, first requires several live world
|
|
state gates to stay clear, derives one year-sensitive random threshold from selected-year fields
|
|
plus world width, then scans the region collection for eligible class-0 regions whose transient
|
|
dwords `[region+0x276]` and `[region+0x302]` are both clear and which fail the city-connection
|
|
peer probe `0x00420030(1,1,0,0)`. When the gate passes it picks one random eligible region,
|
|
derives one small severity bucket from `[region+0x25e]`, stores the scaled amount back into
|
|
`[region+0x276]`, and appends one queued `0x20`-byte record through `0x004337c0` with payload
|
|
seed `0x005c87a8`, literal kind `7`, zero promotion-latch dword `[node+0x0c]`, the chosen region
|
|
id at `[node+0x10]`, that amount at `[node+0x14]`, and sentinel tails `-1/-1` in
|
|
`[node+0x18/+0x1c]`. That append helper is now grounded directly too: `0x004337c0` allocates one
|
|
zeroed linked `0x20`-byte node, copies one string or payload seed into `[node+0x04..]`, stores
|
|
the six fixed dwords into `[node+0x08]` through `[node+0x1c]`, and appends the finished node to
|
|
the singly linked list rooted at `[state+0x66a6]`. The queued family is no longer one unnamed
|
|
gameplay lane either. Local dispatch through `0x00437c00` now resolves kinds `0/4` as fixed
|
|
custom-modal rows, kinds `1/2` as no-op success rows, kind `3` as the direct world-side two-arg
|
|
branch through `0x004dc540`, kind `5` as the one-arg world-side branch through `0x004f29c0`,
|
|
kind `6` as the route-entry-validated branch into `0x00436820`, kind `7` as the region-focused
|
|
custom-modal owner `0x004c7520`, and kind `8` as the two-arg branch through `0x004f2d80`.
|
|
`0x004c7520` is no longer opaque: it requires scenario latch `[0x006cec74+0x277]`, stores the
|
|
queued region id in `0x006cfe80`, allocates one helper object into `0x006cfe88`, opens the
|
|
callback-driven modal through `0x004c98a0` with callbacks `0x004c72f0` and `0x004c73c0`, and on
|
|
affirmative result `0x3f2` resolves the selected region through `0x0062bae0` before recentering
|
|
the live world through `0x00433900`. That also closes the periodic producer side: `0x00422100`
|
|
is no longer just “some scaled region event,” it is the class-0 region picker that queues this
|
|
specific region-focus modal record, with the scaled amount preserved alongside the queued region
|
|
id for the later service family. So the periodic region-selection lane now ties directly into one
|
|
specific queued kind instead of only a generic queue family. One neighboring owner is tighter now too: `0x004358d0` walks the
|
|
same live region collection and services those pending amounts after linked-site refreshes. When a
|
|
region's pending amount at `[region+0x276]` is live and the city-connection peer probes
|
|
`0x00420030` and `0x00420280` can resolve one matching peer site plus linked company through
|
|
`0x0047efe0`, it formats one localized notice from region name `[region+0x356]`, world scalar
|
|
`[region+0x23a]`, and the pending amount, publishes that notice through `0x004554e0`, posts the
|
|
amount into company stat slot `4` through `0x0042a080`, then clears `[region+0x276]` and stamps
|
|
completion latch `[region+0x302] = 1`. When no peer-company branch is available and byte
|
|
`[region+0x316]` is still clear, the same owner publishes one alternate one-shot notice from the
|
|
same amount and region scalar before setting `[region+0x316]`. So the pending-region bonus lane
|
|
is no longer just a queued setup artifact: it has a concrete later service owner and an explicit
|
|
shell-facing fallback above the same queue family now too. Direct disassembly tightens the
|
|
bridge below that owner as well: `0x004358d0` first requires `[region+0x276]`, then drives two
|
|
separate `0x00420030` gate calls plus one `0x00420280` first-match selector before resolving the
|
|
linked company through `0x0047efe0`; only after that does it emit the success-side company/stat
|
|
update or the one-shot fallback notice. The peer helper itself is more concrete now too:
|
|
`0x00420030` walks collection `0x006cec20`, applies the class match through `0x0042b2d0`, uses
|
|
the optional linked-company filter through `0x0047efe0`, keeps the station-or-transit gate
|
|
`0x0047fd50`, and then tests the candidate status branch through `0x0047de00 -> 0x0040c990`
|
|
before reporting success. The paired selector `0x00420280` is the same scan with the same
|
|
filters, but returns the first matching site id instead of a boolean. So the remaining region gap
|
|
is now squarely the persisted latch/id seam, not the live peer/service logic itself. The
|
|
constructor-side owner is explicit now too:
|
|
`world_region_construct_entry_with_id_class_and_default_marker09_profile_seed` `0x00421200`
|
|
clears `[region+0x276]`, `[region+0x302]`, `[region+0x316]`, and neighboring cached bands at
|
|
record construction time while seeding `[region+0x25a/+0x25e] = 100.0f` and
|
|
`[region+0x31b] = 1.0f`. That rules out “unknown field identity” as the main blocker for this
|
|
lane and leaves post-construction restore or rebuild as the remaining closure target.
|
|
That narrows the next closure target
|
|
as well: ordinary-save probes can stop treating `[world+0x66a6]` persistence as the primary
|
|
blocker, because the checked-in negative results on `q.gms`, `p.gms`, and `Autosave.gms` now make
|
|
the pending-bonus owner plus its peer/linkage strip the first safe static target instead. The
|
|
next pass should therefore ask only three concrete questions: which persisted owner seam rebuilds
|
|
or restores `[region+0x25e/+0x276/+0x302/+0x316]`, which stable region id or class discriminator
|
|
survives save/load strongly enough to drive `0x004358d0`, and how far the city-connection peer
|
|
helpers `0x00420030/0x00420280` plus linked-company resolver `0x0047efe0` can be reused
|
|
directly before the transient queued-notice family matters again. `0x00438710` is the recurring queue
|
|
service owner above `[world+0x66a6]` and `[world+0x66aa]`; the short dirty-mark path is tighter
|
|
now as well, because it checks the per-node promotion-latch dword `[node+0x0c] == 1` rather than
|
|
reusing the queue kind field. `0x00438840` is the tiny
|
|
dispatch-or-fallback sibling: it forwards the currently active queue node at `[world+0x66aa]`
|
|
into `simulation_dispatch_runtime_effect_queue_record_by_kind_into_shell_or_world_handlers`
|
|
`0x00437c00`, or opens the fixed custom modal rooted at localized id `0x153` when no active
|
|
node is staged.
|
|
company-credit side effect. One neighboring narrow counter is bounded too: `0x00422850`
|
|
counts class-0 regions that pass a second `0x00420030` peer-probe variant with fixed flags
|
|
`(1,1,1)` plus one caller-supplied trailing dword, and current callers are the query/script
|
|
dispatch at `0x0042f856` and the later region-stats formatter at
|
|
`0x004d2088`. The
|
|
remaining setup-side uncertainty has therefore narrowed
|
|
again: the region seed and border-overlay pair clearly complete before the `Setting up Players and
|
|
Companies...` banner is posted; `[0x006cec74+0x174]` now looks like the direct building-population
|
|
gate; `[0x006cec74+0x178]` now looks like the direct seeding-burst gate and selected-year-adjust
|
|
policy; and `[0x006cec74+0x68]` now aligns with editor-map mode because the same flag forces the
|
|
`.gmp` family in the shell file coordinators while suppressing the later building and seeding
|
|
branches and diverting the deeper region worker into alternate logic. One write side for that
|
|
`[shell+0x178]` policy is now grounded too: inside `shell_dispatch_ui_command` `0x00464410`,
|
|
command ids `0x9d26..0x9d28` store `command_id - 0x9d26` directly into `[0x006cec74+0x178]`,
|
|
yielding live values `0`, `1`, and `2`. That means the later restore branch is no longer gated
|
|
by an abstract hidden shell latch; at least one of its adjustment inputs is an explicit UI
|
|
launch policy. The negative boundary is tighter now too: current local disassembly still does
|
|
not show `world_entry_transition_and_runtime_bringup` `0x00443a50`,
|
|
`shell_setup_load_selected_profile_bundle_into_payload_record` `0x00442400`, or
|
|
`world_load_saved_runtime_state_bundle` `0x00446d40` republishing that dword from file-backed
|
|
state; a direct full-function sweep on `0x00446d40` still turns up many references to shell root
|
|
`0x006cec74`, but no direct `+0x178` operand. The write-side split is now concrete rather than
|
|
provisional too: current full-binary xrefs still only ground direct stores to stage dword
|
|
`0x00620e94` in the ordinary saved-profile loader `0x00442400` and package-save prelude
|
|
`0x00444dd0 = 0x26ad`, while the direct store to `[0x006cec74+0x178]` stays in the interactive
|
|
command dispatcher `0x00464410`. The `319` lane itself is no longer the
|
|
open structural gap; it now clearly owns chairman-profile slot seeding, profile-record
|
|
materialization, a shell editor surface over the same local record family, and a separate
|
|
live-company presentation path through the company-list window. The later interior order of that
|
|
same `319` lane is tighter now too: after the route-entry collection refresh on `0x006cfca8` it
|
|
refreshes the auxiliary route-entry tracker collection `0x006cfcb4`, then runs
|
|
`placed_structure_collection_refresh_local_runtime_records_and_position_scalars` `0x004133b0`,
|
|
which first drains the queued local-runtime rebuild ids through collection `0x0062b2fc` and then
|
|
sweeps the live placed-structure collection `0x0062b26c` for the later position-triplet side
|
|
refresh,
|
|
then a flagged world-grid cleanup sweep through the compact grid-flag query
|
|
`0x00448af0` plus the neighboring local chunk-cell write helper `0x00533fe0`, and only after
|
|
that the later route-entry post-pass at `0x00491c20`. The same `319` lane is tighter internally
|
|
now too:
|
|
the surrounding placed-structure collection side is no longer just the per-record loader family.
|
|
`0x004131f0` now cleanly constructs and stream-loads the live placed-structure collection,
|
|
`0x00413230` constructs the empty runtime pool, `0x00413280` stream-loads tagged placed-structure
|
|
entries with progress publishing, one temporary per-entry shim through `0x0040c950/0x0040c970`,
|
|
and one evenly distributed `0x00ccb9e8` progress step from the saved base scalar, `0x00413260`
|
|
is the matching release-and-free owner, and
|
|
`0x00413550` now clearly resolves one site id, re-enters `0x0040e080` to release local runtime
|
|
and linked-site follow-on state, and only then unlinks the entry from the live collection. The
|
|
adjacent helper strip is tighter too: `0x00413620` is the collection-wide linked-peer overlay
|
|
refresh sweep above `0x0040d2d0`; `0x00413580` is the periodic quarter-subset route-style sweep
|
|
that derives one four-way start bucket from scenario byte `[world+0x11]` and then touches every
|
|
fourth live record; `0x00413660` and `0x004136e0` are the neighboring owner-color
|
|
and scalar publish sweeps; `0x00413750` is the shared mode-`3/6` linked-site preview membership
|
|
refresh owner; `0x00413860` is the collection-side center-cell roster sweep above `0x0040cd10`;
|
|
`0x004138b0` is the route-link cleanup sweep keyed by one center-cell `u16` roster token;
|
|
`0x004138f0` counts live placed structures whose cached candidate id `[site+0x3d0]` matches one
|
|
caller-supplied structure id; `0x00413940` walks the same matching subset and accumulates source
|
|
field `[source+0x141]` from `0x0040cec0` with a floor of `1`; `0x004139a0` counts entries whose
|
|
linked peer passes the narrower station-or-transit gate `0x0040d230`; `0x00413a00/0x00413aa0`
|
|
narrow that same linked-peer subset to candidate class `3` and `4`; and `0x00413b40` is the
|
|
subtype-`4` companion counter whose last gate is the raw linked-instance candidate byte `0xb9`.
|
|
That `0x00413940` sum is now the direct link-count scale factor consumed by `0x0041e7be` above
|
|
the four cargo-summary banks.
|
|
One neighboring year-side owner is tighter now too: `0x00435b50` is the shared year-threshold
|
|
and structure-milestone news pass beneath periodic simulation and startup bring-up. It suppresses
|
|
itself when the cached previous year still matches or scenario gate `[0x006cec78+0x46c38]` is
|
|
live, then publishes fixed year notices for `1865/1895/1920/1958`, formatted numeric notices for
|
|
`1850/1900/1950`, and later structure-milestone notices keyed by live counts of specific placed
|
|
structures resolved through `0x00412af0` and counted through `0x004138f0`, appending the finished
|
|
records into the existing fixed-record/news lanes at `0x006cea4c` and `0x004337c0` rather than
|
|
through a separate hidden journal family.
|
|
before that later world and shell reactivation tail, `world_entry_transition_and_runtime_bringup`
|
|
runs two separate recipe-runtime rebuild moments rather than one monolithic import step. The
|
|
earlier call at `0x00443ebc` fires immediately after the named candidate-availability collection
|
|
at `[world+0x66b2]` has been restored from fixed `0x22`-byte rows and before the neighboring
|
|
candidate filter/count rebuilds `0x00412c10/0x00412bd0` plus the year-derived follow-ons
|
|
`0x00434130/0x00436af0`. The later call at `0x00444ac1` sits inside the explicit `0x197`
|
|
checkpoint after `world_publish_shell_controller_progress_scalar_from_year_thresholds_or_selector_overrides`
|
|
`0x004354a0` and the territory-side sweep `0x00487de0`, and only then falls through into the
|
|
named-candidate availability preseed `0x00437737` plus the later candidate-filter refresh
|
|
`0x00412c10`. The post-bundle status and runtime refresh phase around those checkpoints still
|
|
posts progress ids `0x196` and `0x197` through `0x005193f0/0x00540120` with paired `0x004834e0`
|
|
follow-ons, and refreshes the live event collection at `0x0062be18` through
|
|
`scenario_event_collection_refresh_runtime_records_from_packed_state` `0x00433130`. That preseed
|
|
lane is tighter now too: it walks the live candidate pool at `0x0062b268` in reverse, forces one
|
|
override bit `0` whenever the candidate availability word `[candidate+0xba/+0xbb]` is already
|
|
nonzero, derives the remaining zero-word subtype cases from the local `2 xor [candidate+0x32]`
|
|
parity check, and only skips those subtype-derived rows when the copied stage counter from
|
|
`0x00620e94` is nonzero before re-entering `0x00434f20` on the candidate stem at `[candidate+0x04]`. The event-side
|
|
`.smp` bridge is
|
|
tighter now too: the save-side companion `0x00433060` opens chunk `0x4e99`, writes version dword
|
|
`0x3e9`, first walks the live event collection through
|
|
`scenario_event_prepare_runtime_record_text_bands_for_packed_state_save` `0x0042da90`, emits the
|
|
collection-side packed metadata through `0x00517d90`, then opens chunk `0x4e9a` and serializes
|
|
each event through `scenario_event_serialize_runtime_record_into_packed_state` `0x00430d70`
|
|
before closing with `0x4e9b`; the restore-side sibling `0x00433130` then re-enters
|
|
`scenario_event_refresh_runtime_record_from_packed_state` `0x0042db20` on each live record
|
|
during bring-up. The per-record split is narrower too: `0x0042da90` services the six fixed
|
|
The surrounding tagged collection-load strip is explicit now too. Before that same late
|
|
reactivation tail continues, `world_entry_transition_and_runtime_bringup` reloads the main route
|
|
collection `0x006cfca8` through
|
|
`route_entry_collection_refresh_records_from_tagged_bundle_and_reseed_tracker_sidecars`
|
|
`0x00493be0`, the auxiliary route-entry tracker collection `0x006cfcb4` through
|
|
`route_entry_tracker_collection_refresh_records_from_tagged_bundle` `0x004a41b0`,
|
|
placed-structure local runtime records through `0x004133b0`,
|
|
the world-manager family at `0x006ceb9c` through `0x00477780`, the geographic-label database at
|
|
`0x006ada80` through `geographic_label_database_refresh_records_from_tagged_bundle` `0x00461580`,
|
|
the placed-structure dynamic-side-buffer tagged lane on `0x006cec20` through
|
|
`placed_structure_collection_refresh_dynamic_side_buffers_from_tagged_bundle` `0x00481210`, the
|
|
linked-route-object collection at `0x0062ba84` through
|
|
`linked_route_object_collection_refresh_records_from_tagged_bundle` `0x0041d3f0`, the
|
|
city-database entry collection at `0x006cea50` through
|
|
`city_database_entry_collection_refresh_records_from_tagged_bundle` `0x00474540`, the live region collection at `0x0062bae0` through
|
|
`world_region_collection_refresh_records_from_tagged_bundle` `0x00421510`, the live territory
|
|
collection at `0x006cfc9c` through `territory_collection_refresh_records_from_tagged_bundle`
|
|
`0x00487c20`, and the support family at `0x0062b244` through
|
|
`support_collection_refresh_records_from_tagged_bundle` `0x0040b5d0`.
|
|
The matched save side is explicit too. Inside
|
|
`map_bundle_open_reference_package_and_serialize_early_world_datasets` `0x00444dd0`, the same
|
|
route collections are written back through
|
|
`route_entry_collection_serialize_records_into_tagged_bundle` `0x00491c60` and
|
|
`aux_route_entry_tracker_collection_serialize_records_into_tagged_bundle` `0x004a4240`. The
|
|
tracker per-entry save callback
|
|
`aux_route_entry_tracker_serialize_noop_per_entry_payload_stub` `0x00494ef0` is currently a bare
|
|
`ret 4`, so that tracker lane persists collection-side metadata and live ids without additional
|
|
per-entry payload.
|
|
The adjacent route-link family at `0x006ada90` is tighter now too: current world-entry bring-up
|
|
only refreshes its direct indexed-collection header or id band through `0x00518680`, and the
|
|
later live endpoint or grid state is regenerated afterward by
|
|
`placed_structure_route_link_collection_recompute_all_endpoint_pair_state` `0x004682c0` and the
|
|
broader rebuild sibling `0x00468300` rather than by a separate tagged per-record payload lane.
|
|
text-band families at `[record+0x0e0/+0x401/+0x4ca/+0x593/+0x65c/+0x725]`, while `0x00430d70`
|
|
writes the standalone runtime condition-row chain plus the four grouped runtime-effect row chains
|
|
into the packed stream. The recipe rebuild lane itself is
|
|
tighter now too: `0x00435630` resolves both token lanes through the exact live cargo-name matcher
|
|
`cargo_collection_find_entry_id_by_exact_name` `0x0041e9f0`, fills empty token strings from the
|
|
first live cargo entry before that match, and in mode `3` keeps reseeding the primary lane from
|
|
that same first live cargo name until the primary and subordinate strings no longer compare equal
|
|
through `0x005a57cf`. The importer-side bridge is tighter now too: each of the twelve recipe
|
|
books first clamps the shared production-cap float that precedes the five `0x30`-byte line
|
|
records up to a fixed minimum `4.0`, then writes each book's active nonzero-mode line count into
|
|
the paired runtime count lane beside the imported `0xbc` descriptor strip. The five runtime
|
|
slots are zeroed and seeded with fixed year-window defaults before any nonzero-mode line is
|
|
imported, and each nonzero line amount is normalized to at least `1.0` before the mode `1/3`
|
|
direct primary half and mode `2/3` one-row subordinate half are populated. The matcher return
|
|
value is explicit now too: `0x0041e9f0` returns one live cargo entry id or `0`, and the importer
|
|
writes that value straight into `[desc+0x1c]` and `[desc+0x44]` without any post-match failure
|
|
guard. The editor-side `Port/Warehouse Cargos` page is tighter in the same way: its constructor
|
|
`0x004cf910` exact-matches the persisted `+0x08/+0x1c` token strings against visible live cargo
|
|
names only to seed selector indices, leaves unmatched strings at the zero-selector default, and
|
|
separately derives the bounded usage summaries `508/509` by scanning the live city-or-region
|
|
collection for rows whose current recipe ordinal `[entry+0x2f2]` matches the selected book. The
|
|
paired handler `0x004d0040` then writes the selected cargo names back into those token slots
|
|
verbatim. That handler is tighter now too: `0x59d8` is the top-level shared production-cap field
|
|
and writes `book+0x3ed` after clamping the parsed value to `<= 8`; `0x59d9` only opens the
|
|
rename modal over the current `0x3c`-byte book-name span; `0x59da/0x59db` cycle the selected
|
|
recipe book backward or forward modulo `12`; and `0x59de` commits the selected book ordinal into
|
|
`0x006cffa4`. The five per-line write bands are now exact too: `0x5a0a..0x5a0e` write the mode
|
|
dwords at `book+0x3f1+line*0x30`, `0x5a1e..0x5a22` copy one live cargo name into the supplied
|
|
token lane at `book+0x3f9+line*0x30`, `0x5a32..0x5a36` copy one live cargo name into the
|
|
demanded token lane at `book+0x40d+line*0x30`, and `0x5a50..0x5a54` write the per-line amount
|
|
float to `book+0x3f5+line*0x30` after clamping the parsed value to `<= 6`.
|
|
So the stronger current boundary is now explicit on both sides: there is still no special marker
|
|
decode before import, and unmatched token strings simply survive in scenario state until
|
|
`0x0041e9f0` returns cargo id `0`.
|
|
Mode `2` copies the normalized line amount into `[desc+0x48]`, while mode `3` overwrites
|
|
that same subordinate amount with literal `1.0` after the token-divergence loop succeeds.
|
|
After the full twelve-book sweep the helper explicitly re-enters
|
|
`structure_candidate_collection_rebuild_runtime_records_from_scenario_state` `0x00412d70` when
|
|
the live candidate collection exists. That keeps the strongest current static split narrow and
|
|
concrete: mode-zero demand rows can still preserve readable cargo-name text in the saved recipe
|
|
books, but only the nonzero imported rows reach the live `0xbc` descriptor array. The remaining
|
|
supply-marker gap is now narrower too: current local evidence shows no special decode path at
|
|
all before exact-name resolution. The editor-side page only reflects selector ordinals when the
|
|
persisted token strings already match visible live cargo names, the normal in-game editor path
|
|
`0x004d0040` writes selected cargo names back into those token slots verbatim, and the importer
|
|
itself writes the exact-match result ids straight into `[desc+0x1c]` and `[desc+0x44]`,
|
|
defaulting failed matches to cargo id `0`. The reset side narrows that authorship boundary
|
|
further too:
|
|
`0x00436d10` only zero-fills the recipe books and reseeds their `# %1` name lane, so those
|
|
marker-like token strings are not coming from the built-in reset template. A fresh direct-hit
|
|
scan on the recipe-book root `0x0fe7` also failed to surface any new live writer beyond the
|
|
already-grounded reset, save/load, and editor-panel families. The one suspicious later hit
|
|
neighborhood around `0x00500c73/0x00500d3f` turns out not to be another recipe writer at all:
|
|
it is a shell control-construction strip using localized ids `0x0fe6/0x0fe8/0x0fe9` as UI
|
|
resource ids, not `[world+0x0fe7]` field accesses. Checked map/save pairs then preserve those raw
|
|
marker payloads byte-for-byte. So the load/save ownership seam is closed at the current evidence
|
|
level: within the local binary there is no surfaced non-editor author or hidden decode stage for
|
|
those marker families before the saved recipe books are exact-matched back into live descriptor
|
|
arrays.
|
|
The first grounded consumer beneath that import bridge is tighter now too:
|
|
`structure_candidate_query_cargo_runtime_summary_channels` `0x00412650` lazily stamps the current
|
|
scenario year into `[candidate+0x788]`, rebuilds four banks across both mode banks `0/1`, and
|
|
returns one direct primary-cargo scalar channel, one cap-share primary-cargo scalar
|
|
channel, one nonzero-mode subrow channel, and one zero-mode cap-scaled subrow channel for a
|
|
requested cargo id. The two primary-cargo banks index from `[desc+0x1c]`, while both subordinate
|
|
row banks index from `[desc+0x44+row*0x1c]`; nonzero-mode descriptors only feed the nonzero-mode
|
|
subrow bank, while mode-`0` descriptors either add their direct scalar to `[this+0x03a]` or, when
|
|
subrows are present, add one cap-share scalar to `[this+0x0a4]` and one cap-scaled row
|
|
contribution to `[this+0x178]`. That keeps the cargo-id-`0` boundary narrow and concrete too:
|
|
if marker rows still fail `0x0041e9f0`, they will hit the first bank bucket inside `0x00412650`,
|
|
but the broader steady-state caller layer already treats cargo id `0` as a fallback or sentinel
|
|
request rather than a normal cargo lane: the candidate-service bitset owner loops from cargo id
|
|
`1`, and the placed-structure sweep routes explicit cargo-id-`0` requests into the linked-site
|
|
classification side instead of the ordinary cargo-reference helper. That keeps the local bridge
|
|
closed at the current evidence level: marker rows can still arrive as opaque preserved scenario
|
|
payload, but there is no remaining importer or consumer-side ownership seam to map here. The runtime descriptor
|
|
construction is tighter in the same way: each imported `0xbc` slot is
|
|
zeroed first, seeded with fixed year-window defaults `0x0708..0x270f`, then filled only for
|
|
nonzero source-line modes; mode `2/3` writes the supplied token lane through `+0x08 -> +0x1c`
|
|
plus the direct annual amount at `[desc+0x04]`, while mode `1/3` writes one subordinate-row
|
|
demand half through `+0x30 -> +0x44` with `[desc+0x2c] = 1`, and production mode `3` forces that
|
|
demand-row amount to `1.0` at `[desc+0x48]` instead of reusing the entered annual amount.
|
|
The immediate helper strip under that bridge is tighter now too. `0x00411ee0` is no longer just
|
|
a vague summary refresh: it clears the two compact cargo-id tables at `[candidate+0x79c]` and
|
|
`[candidate+0x7a0]`, clears the per-cargo float band `[candidate+0xa1..+0xb8]`, fills one local
|
|
`0x35`-cargo status scratch where `1` means referenced and `2` means currently year-active. The
|
|
year window is narrower than the earlier shorthand too: status `2` only applies while
|
|
`start_year <= current_year < end_year`, using live world year `[0x006cec78+0x0d]` or fallback
|
|
year `0x709` when no world is present. The helper keeps that maximum status per remapped cargo id
|
|
through `0x0062ba8c+0x9a`, and then compacts the
|
|
`status>=1` and `status>=2` sets back into the two emitted cargo-id tables with counts
|
|
`[candidate+0x7a4]` and `[candidate+0x7a8]`. The same scan publishes the stronger production-side
|
|
split too: mode-`0` descriptor rows are cap-scaled by `[candidate+0x2a] / [desc+0x04]`, while
|
|
nonzero-mode rows bypass that normalization and keep their direct row amount. Below that, `0x00411d50` is the narrow
|
|
descriptor-pattern predicate that returns true only when every imported descriptor keeps mode `0`
|
|
and at least one descriptor has no subordinate rows, while `0x00411da0`, `0x00411e10`, and
|
|
`0x00411e50` are conservative fixed-table accessors over candidate slot `[candidate+0x798]`,
|
|
exposing one copied name plus either a scalar pair or scalar triplet from the same fixed row in
|
|
`0x005ed338..0x005edca4` rather than a separate loader family.
|
|
The sibling post-import flag pass `0x00411ce0` is tighter in the same way: for subtype byte
|
|
`[candidate+0x32] == 2`, `[candidate+0x790]` records whether any mode-`0` descriptor exists,
|
|
while `[candidate+0x78c]` stays armed only when every mode-`0` descriptor carries at least one
|
|
subordinate row, or when no mode-`0` descriptors exist at all.
|
|
One later subphase is tighter now too: before the broad world-reactivation sweep it
|
|
posts progress ids `0x32dc/0x3714/0x3715`,
|
|
reloads one `0x108`-byte packed profile block through `0x00531150`, conditionally copies staged
|
|
runtime-profile bytes back into `0x006cec7c` while the file-backed profile rehydrate latch
|
|
`[profile+0x97]` is set, mirrors the grounded campaign/setup byte `[profile+0xc5]` and sandbox
|
|
launch byte `[profile+0x82]` into world bytes `[world+0x66de]` and `[world+0x66f2]`, and
|
|
restores the selected-year lane through a tighter two-stage calendar path than before. Current
|
|
local disassembly now shows the raw saved lane at `[profile+0x77]` first feeding
|
|
`calendar_pack_year_and_component_bytes_to_packed_tuple_dwords` `0x0051d3f0` with constant components
|
|
`(month=1, day=1, subphase=0, tick=0)`, which writes the resulting Jan-1-style tuple dwords
|
|
into `[world+0x05/+0x09]`. Only after that seed does the same lane enter one mode-sensitive
|
|
adjustment branch: non-editor startup mode can decrement the lane by `1` or `3` depending on
|
|
shell-state editor gate `[0x006cec74+0x68]`, shell-side selected-year-adjust policy
|
|
`[0x006cec74+0x178]`, and the saved special-condition slot `[0x006cec78+0x4af7]`, and only that
|
|
save/load bridge is narrower on the candidate side too: the constructor-side load owner
|
|
`structure_candidate_collection_construct_and_stream_load_runtime_records` `0x004131f0`
|
|
seeds global pool `0x0062b268` and immediately re-enters the broader collection importer
|
|
`structure_candidate_collection_stream_load_rebuild_runtime_summaries_and_refresh_named_availability`
|
|
`0x00412fb0`. That owner streams each packed candidate body back through
|
|
`structure_candidate_stream_load_runtime_record_and_rebuild_cargo_state` `0x004120b0`, reruns the
|
|
scenario-side recipe projection at `0x00412d70`, refreshes the stem-policy lane at `0x00412ab0`,
|
|
rebuilds the collection aggregate subtotal band at `[pool+0x8c..+0x9c]`, repopulates the fixed
|
|
name catalog at `0x0061dbc2/0x0061dc09` for non-subtype-`1` zero-availability candidates whose
|
|
live ids stay within `0x6e`, and then reruns the named-availability pass at `0x00412c10` before
|
|
returning. The surrounding bringup strip is explicit now too: the world-entry load branch passes
|
|
through one bare placeholder `structure_candidate_post_collection_construct_noop_placeholder`
|
|
`0x00411d90` between constructing `0x0062b268` and allocating the auxiliary candidate pool at
|
|
`0x0062b2fc`, so that callsite is no longer an unmapped hole in the candidate-side loader path.
|
|
The same load strip is tighter now too: `0x00412ab0` is the pure stem-policy sweep
|
|
that refreshes candidate dword `[+0xbc]` from defaults `0x1869f/3/4` plus the fixed override
|
|
table at `0x005edca8..0x005edd20`, with the non-default `3/4` branches driven directly by
|
|
post-import flag `[candidate+0x78c]` and subtype byte `[candidate+0x32]`. The per-record loader
|
|
`0x004120b0` now clearly reads the fixed header fields first, allocates the descriptor strip as
|
|
`count*0xbc + 1`, zeroes every imported `0xbc` descriptor slot before import, resolves primary
|
|
mode-`0` cargo names from `+0x08 -> +0x1c` and subordinate row cargo names from `+0x30 -> +0x44`,
|
|
clamps descriptor start year `[desc+0x20]` upward to the resolved cargo availability floor
|
|
`[cargo+0x21]`, and only then reruns `0x00411ee0` plus `0x00411ce0`. Its version gates are
|
|
explicit too: bundles before `0x3ed` omit `[candidate+0x3b..+0xbb]`, bundles before `0x3f2`
|
|
keep the narrow `0x02`-byte form of `[candidate+0xc0]`, nonzero `[candidate+0x4b]` forces
|
|
`[candidate+0x47] = 1.0` and rescales `[candidate+0x43]` to at least `0x1388`, and the later
|
|
stem-index resolution first checks two built-in alias stems before the full fixed row table at
|
|
`0x005ed338..0x005edca4`. The neighboring placed-structure side
|
|
is bounded too: global pool `0x0062b26c` comes from
|
|
`placed_structure_collection_construct_empty_runtime_pool` `0x00413230`, while the paired tagged
|
|
collection owners `0x00413280` and `0x00413440` now own the broader placed-structure stream
|
|
load/save path around tags `0x36b1/0x36b2/0x36b3` and the per-entry virtual load/save slots
|
|
`+0x40/+0x44`. The adjacent auxiliary or source-record side is tighter now too: global
|
|
`0x0062b2fc` comes from
|
|
`aux_candidate_collection_construct_seed_globals_and_helper_bands_then_import_records`
|
|
`0x0041aa50`, which seeds constructor globals `0x0062b2f0/0x0062b2f4/0x0062b2f8`, initializes
|
|
the collection configuration, allocates the three owned helper bands at `[this+0x88/+0x8c/+0x90]`
|
|
through `0x0041a990`, and then tails into the already-grounded tagged import owner
|
|
`0x004196c0` plus the later rebank-or-clone refresh `0x00419230`.
|
|
adjusted lane then feeds
|
|
`calendar_pack_unpacked_components_to_absolute_counter` `0x0051d390` before `world_set_selected_year_and_refresh_calendar_presentation_state`
|
|
`0x00409e80` stores the final absolute counter into `[world+0x15]` and refreshes
|
|
`[world+0x0d/+0x11]`. That means the restore no longer reads as a direct
|
|
`[profile+0x77] -> [world+0x15]` copy; the raw lane seeds the tuple immediately, but the final
|
|
absolute-counter restore still depends on live shell/startup context. That dependency is tighter
|
|
now too: current local evidence shows `[shell+0x178] == 1` decrementing the restored lane by
|
|
`1`, `[shell+0x178] == 2` subtracting `3`, and otherwise a nonzero
|
|
`[0x006cec78+0x4af7]` supplying the fallback `-1` branch. That field is no longer unresolved:
|
|
current local disassembly now shows `0x00436d10` bulk-zeroing the dword table rooted at
|
|
`[startup+0x4a7f]` through `rep stos`, which includes `+0x4af7`, while the editor-side special
|
|
conditions owner at `0x004cb2b0/0x004cb8e0` counts and commits that same 49-entry table from the
|
|
static rule descriptors at `0x005f3ab0`. The `.smp` save or restore family now grounds that live
|
|
band directly too: `world_runtime_serialize_smp_bundle` `0x00446240` writes `49` dwords from
|
|
`[world+0x4a7f..+0x4b3f]` plus one trailing scalar at `[world+0x4b43]`, and
|
|
`world_load_saved_runtime_state_bundle` `0x00446d40` restores the same fixed `0xc8`-byte band
|
|
symmetrically. The surrounding `.smp` lane is tighter too: at version `>= 0x3f1` the save path
|
|
also writes the late setup-preview payload block at `[world+0x66be]` through chunk ids
|
|
`0x2ee0/0x2ee1`, and the restore path reads that same pair back while older bundles clear the
|
|
compatibility tail at `[world+0x6987]`; the shared helper `0x00441ec0` inside that sidecar
|
|
family is tighter now too, but the save split is explicit now: the package-save branch at
|
|
`0x00444f42/0x00444f47` calls `0x00442ba0` and then immediately re-enters `0x00441ec0`, while
|
|
the `.smp` serializer branch at `0x00446312` instead calls `0x00442ba0` and then emits `0x2ee0`,
|
|
writes the full `0x403c2` payload directly through `0x00531030`, and closes `0x2ee1` itself.
|
|
`0x00441ec0` therefore belongs to the companion-image or staged-object sidecar transport strip,
|
|
not to the ordinary `.smp` slot-table write path. The restore-side boundary is narrower than that
|
|
file format now too: current local evidence still does not show either `0x00441ec0` or the
|
|
`.smp` restore path inside `0x00446d40` writing that restored leading dword back into
|
|
`0x00620e94`, and the same negative read currently applies to shell dword
|
|
`[0x006cec74+0x178]`: the load/restore family consumes it for selected-year and seeding
|
|
decisions, but the grounded writer is still the interactive command path in `0x00464410`
|
|
rather than a file-backed restore. That stage-versus-policy split is explicit on the consumer
|
|
side now too: `0x00436d10` uses `[0x006cec74+0x178]` only for the `-1` or `-3` selected-year
|
|
adjustment branch after `[profile+0x77]` seeds the Jan-1 tuple, `0x004384d0` only uses the same
|
|
shell dword to gate the later economy burst, `0x00437b20` derives its loop count from that shell
|
|
dword before the special-condition override at `[world+0x4af7]`, while the save-backed stage
|
|
dword `0x00620e94` stays on the separate threshold and candidate-preseed side through
|
|
`0x00437737` and `0x00444dc5`. The save-side exporter `0x00442ba0` also shows the
|
|
concrete shape of that block by copying one `0x403c2`-byte payload record, forcing validity byte
|
|
`+0x00 = 1`, patching current world dimensions into `+0x01/+0x05`, mirroring shell bytes into
|
|
`+0x09..+0x0b`, and normalizing the embedded `0x100 x 0x100` preview pixels at `+0x03c2`. That
|
|
byte trio is tighter now too: current local disassembly grounds `+0x09/+0x0a` as direct mirrors
|
|
of shell-controlled sidecar dwords `[0x006d4024+0x11471a/+0x11471e]`, while `+0x0b` is the low
|
|
byte of shared dword `0x0062bec4`, which the package-save coordinator seeds from the sibling
|
|
selector pair `[0x006d4024+0x11472a/+0x11472e]` before export. The shell-side provenance is
|
|
tighter in the same way: the display-runtime defaults path around `0x0051ee48..0x0051ee85`
|
|
initializes those four dwords together, and the broader
|
|
`shell_settings_window_handle_message_dispatch_and_persist_display_runtime_sidecar_family`
|
|
`0x00464c80` later owns the direct toggle strip for controls `0xe101..0xe104`, including the
|
|
grounded implication rules `!0x11471e -> clear 0x11472a` and `(0x11472a || 0x11472e) -> set 0x11471e`.
|
|
The two
|
|
later sidecar gates are therefore tied
|
|
back into that copied layout directly: package-save reads `[world+0x66c8]` and `[world+0x66c9]`,
|
|
so the exported payload bytes `+0x0a` and `+0x0b` are the same companion-image and
|
|
companion-payload gates in the live world block. The producer boundary is tighter now too:
|
|
current local xrefs still do not show standalone byte-local writers for `[world+0x66c8/+0x66c9]`,
|
|
but the same search now shows that they are not orphan fields either. The ordinary producer is
|
|
the wider payload exporter chain itself: `0x00464c80` toggles the shell-side source dwords,
|
|
`0x00445de0` reseeds selector dword `0x0062bec4`, and `0x00442ba0` copies those values into
|
|
payload bytes `+0x0a/+0x0b`. The live world bytes are then written only by the bulk
|
|
`[world+0x66be]` payload-copy lanes, namely the `.smp` restore path `0x00446d40` and the
|
|
multiplayer selector mirror `0x0046cf40`, both of which copy the full setup-preview payload
|
|
block containing those two bytes.
|
|
companion-payload sidecar gates inside the broader `0x66be` block.
|
|
Both sides also preserve the same twelve `0x4e1` recipe books at
|
|
`[world+0x0fe7]` as one exact `cap dword + 0x3d-byte header + five repeated line tuples`
|
|
structure, where each repeated `0x30`-byte line is serialized field-by-field as mode dword
|
|
`+0x00`, annual amount float `+0x04`, supplied-token window `+0x08`, and demanded-token window
|
|
`+0x1c` before the wider world-cell loops continue. One
|
|
serializer-side negative boundary is explicit now too: after the save path emits the six-dword
|
|
economic tuning band at `[world+0x0be2..+0x0bf6]`, it spends its next large loops on per-cell
|
|
world-grid, overlay-mask, sidecar-plane, and secondary-raster bit serialization and only then
|
|
jumps directly to the recipe-book root at `[world+0x0fe7]`. So the later pre-recipe plateau is a
|
|
real save-neighbor family, but current local evidence no longer supports treating it as one
|
|
contiguous `.smp` serializer-owned slab beyond that leading six-dword tuning band. Slot `30`
|
|
in that table is localized pair `3722/3723`
|
|
`Disable Cargo Economy`, so `+0x4af7` now reads as the live copy of that saved scenario rule,
|
|
not a startup-runtime-only mystery latch. The neighboring fixed reads line up with the same rule
|
|
cluster too: `+0x4aef` is slot `28` `Completely Disable Money-Related Things`, `+0x4af3` is slot
|
|
`29` `Use Bio-Accelerator Cars`, `+0x4afb` is slot `31` `Use Wartime Cargos`, `+0x4aff` is slot
|
|
`32` `Disable Train Crashes`, `+0x4b03` is slot `33` `Disable Train Crashes AND Breakdowns`, and
|
|
`+0x4b07` is slot `34` `AI Ignore Territories At Startup`. The remaining restore-side dependency
|
|
is now concrete rather than mysterious: the year adjustment still depends on live shell policy
|
|
`[shell+0x178]`, but that policy already has grounded UI writers and the `+0x4af7` input itself
|
|
is save-derived scenario rule data rather than something that requires runtime tracing to
|
|
discover. Its read-side family is no longer isolated to the selected-year
|
|
restore either: it also shapes the chunk size in
|
|
`simulation_run_chunked_fast_forward_burst` `0x00437b20` and appears in candidate/local-service
|
|
selection and station-detail-side scoring branches around `0x0047f910`, `0x00410d87`, and
|
|
`0x005069c6`, which now makes this whole slot cluster look like broader runtime consumers of
|
|
scenario special conditions rather than one startup-only mode enum. That startup-side consumer
|
|
split is tighter now too: inside the localized `Computing Transportation and Pricing...` bring-up
|
|
lane, `world_preseed_named_candidate_availability_records_from_live_pool` `0x00437737` only runs
|
|
before global stage counter `0x00620e94` reaches `0x26ad`, reverse-walks the live candidate pool,
|
|
and seeds the scenario-side named availability table through `0x00434f20` with one override bit
|
|
derived directly from current live candidate state. Any nonzero availability pair
|
|
`[candidate+0xba/+0xbb]` forces that upsert with override bit `0`; otherwise the zero-availability
|
|
path derives its bit from subtype parity on `[candidate+0x32]` through the local `2 xor subtype`
|
|
branch and only skips those subtype-driven cases when the copied stage counter is already nonzero.
|
|
The same startup strip then flows into `world_seed_default_chairman_profile_slots` `0x004377a0`,
|
|
which compacts the 16 staged chairman slot records at `[world+0x69d8]`, writes the first-pass
|
|
selector bytes into `[profile+0x87+i]`, allocates one fresh persona-record id for each nonzero
|
|
selector, and only after that materializes the named-profile rows through `0x00476140`. The
|
|
neighboring materializer `world_build_chairman_profile_slot_records` `0x00437220` is tighter now
|
|
too: it first rebuilds one local `0x29`-byte occupied-persona mask from the two `0x48`-byte
|
|
staging records rooted at `[world+0x69db]`, optionally waits on the multiplayer preview owner at
|
|
`0x006cd8d8`, then resolves selector `0` through the first unused persona ordinal in
|
|
`[world+0x6987]` while selectors `<0x64` map to `selector-1` and selectors `0x64+` map to the
|
|
later-opponent range. That same pass copies the staged tuning dword from `[slot+0x04]` into
|
|
`[profile+0x154/+0x158]`, can clear or set `[profile+0x293]` on the multiplayer-preview side
|
|
path, and finally seeds `[world+0x25]` plus `[world+0x21]` from the resolved first profile row.
|
|
So the save-derived special-condition band no longer sits beside anonymous startup glue: the
|
|
bring-up path now has one concrete candidate-availability mirror at `0x00437737`, one concrete
|
|
chairman-slot selector seeding pass at `0x004377a0`, one concrete chairman-profile materializer
|
|
at `0x00437220`, and then the economy burst `0x00437b20`, whose own loop count is now tighter
|
|
than before because a nonzero `[world+0x4af7]` forces the chunk count to literal `0x150` instead
|
|
of leaving the shell-side `[0x006cec74+0x178]` count in control. One file-side anchor is now tighter too: the checked
|
|
classic and 1.05 `gmp/gms/gmx` corpus does expose the same aligned
|
|
`0x0d64..0x0e2c` `50`-dword band as the grounded `.smp` runtime save or restore copy into
|
|
`[world+0x4a7f..+0x4b43]`, but most checked file families only populate a sparse subset of that
|
|
band. The first `36` dwords still behave like the older inferred fixed rule matrix with hidden
|
|
slot `35` fixed to sentinel value `1`, while the trailing `13` unlabeled rule lanes plus one
|
|
scalar vary much more selectively by file family. Current local corpus scans make that split
|
|
concrete: the grounded 1.05 scenario-save family (`p.gms`, `q.gms`) stably lights lanes
|
|
`35, 37, 39, 44, 45, 46, 47, 48`; the base 1.05 save family (`Autosave.gms`, `nom.gms`) only
|
|
shares lane `35` stably and otherwise varies sparsely through `42`, `45`, and `47`; the checked
|
|
grounded 1.05 maps, the lone 1.05 alt save, and the visible sandbox-family `.gmx` files keep
|
|
only the sentinel lane `35` nonzero. So the current loader boundary is narrower than before: the
|
|
`.smp` path still gives a grounded direct runtime-band restore, and checked `gmp/gms/gmx` files
|
|
now show a partially populated projection of that same aligned band rather than a wholly separate
|
|
fixed record family. The overlap against the later scalar window is now explicit too: trailing
|
|
band indices `36..49` are byte-identical with post-window offsets `0x00..0x34`, so every nonzero
|
|
lane in that prefix of the post-sentinel scalar window is also a nonzero lane in the aligned
|
|
runtime-rule band. That means the real “other fields” boundary inside the post-sentinel window
|
|
starts only at `0x0e2c`: `0x0df4..0x0e2c` is the aligned-band overlap prefix, while
|
|
`0x0e2c..0x0f30` is the later tail that still looks like save-side scalar state. Local corpus
|
|
scans now make that tail split more specific. The base 1.05 save family
|
|
(`Autosave.gms`, `nom.gms`) shares a stable tail subset at relative offsets
|
|
`0xb4`, `0xc0`, `0xe0`, `0xfc`, and `0x100`, with additional per-file lanes around them. The
|
|
1.05 scenario-save family (`p.gms`, `q.gms`) has a much denser stable tail covering
|
|
`0x08`, `0x0c`, `0x10`, `0x14`, `0x20`, `0x24`, `0x28`, `0x30`, `0x34`, `0x3c`, `0x5c`,
|
|
`0x6c`, `0xa0`, `0xa8`, `0xbc`, `0xc0`, `0xc4`, `0xc8`, `0xcc`, `0xdc`, `0xe0`, `0xe4`,
|
|
`0xe8`, `0xf4`, `0xf8`, and `0xfc`; those values still differ per save, but the occupancy is
|
|
stable. The lone 1.05 alt save (`g.gms`) only lights `0x20`, `0x34`, `0xf0`, and `0xf4`.
|
|
Grounded map families and classic saves keep the tail zeroed, while the only current map-side
|
|
outlier remains `Tutorial_2.gmp` under the broad unknown map-family bucket. The immediately
|
|
following fixed file window at `0x0df4..0x0f30` is now bounded separately as well: checked maps
|
|
and classic saves leave that whole post-sentinel band zeroed,
|
|
while checked 1.05 saves carry sparse nonzero dwords there, many of which decode cleanly as
|
|
normal little-endian `f32` values. That makes the adjacent band look like a 1.05 save-only
|
|
runtime band rather than scenario-static payload. So the local static seam there is closed: it
|
|
is runtime-save state, now carried conservatively as the 1.05-only late scalar tail beneath the
|
|
aligned runtime-rule base rather than an unnamed ownership gap.
|
|
One numeric alignment inside that band is now exact too: the tail start `0x0e2c` is the same
|
|
relative distance from the aligned runtime-rule base `0x0d64` as live object offset `+0x4b47`
|
|
is from grounded world-rule base `[world+0x4a7f]`, so the bounded tail window
|
|
`0x0e2c..0x0f30` is offset-aligned with live bytes `[world+0x4b47..+0x4c4b]`. The first
|
|
grounded live field at that boundary is no longer anonymous.
|
|
`world_set_outcome_mode_and_copy_cheat_win_or_loss_status_text` `0x004367c0` sets one outcome
|
|
mode in `[world+0x4a73]`, zeros `[world+0x4d]`, snapshots the selected-year lane to
|
|
`[world+0x4c88]`, and then copies localized id `2923` `You lose.` or `2924`
|
|
`You win, cheater...` into `[world+0x4b47]`; `0x00472dd0` formats localized id `3918`
|
|
`%1 has won the game!` with one live profile name and writes that string into the same
|
|
destination; and one compact runtime-effect
|
|
branch inside `world_apply_compact_runtime_effect_record_to_resolved_targets` `0x00431b20` resets
|
|
the same destination to the fixed placeholder token at `0x005c87a8`. That gives a grounded live
|
|
owner above the latch too: `simulation_service_world_outcome_mode_prompt_and_transition_effects`
|
|
`0x00436350` is the frame-serviced consumer of `[world+0x4a73]`, stamping completion latch
|
|
`[world+0x4a77]`, driving the outcome-mode prompt rooted at localized id `0x169`, and triggering
|
|
the world-side transition paths around `0x482150` while leaving `[world+0x4b47]` as the current
|
|
outcome-status payload source. That gives a grounded live
|
|
interpretation for the start of the tail: `[world+0x4b47]` is the start of a victory or outcome
|
|
status-text buffer, not a float lane. The same evidence also gives a useful caution: those live
|
|
helpers copy up to `0x12c` bytes into `[world+0x4b47..+0x4c73]`, so the current bounded file-tail
|
|
window `0x0e2c..0x0f30` cuts through the first `0x104` bytes of a grounded text field rather
|
|
than ending on a clean live-field boundary. One small continuation probe now tightens that edge:
|
|
the remaining file window `0x0f30..0x0f58` is exactly the last `0x28` bytes needed to reach the
|
|
clean live-field boundary at `[world+0x4c73]`, and checked 1.05 saves still carry sparse nonzero
|
|
bytes in that continuation window rather than a trailing text-looking suffix. Checked 1.05 save
|
|
bytes in the aligned region therefore still do not resemble preserved text; they stay mostly zero
|
|
at the beginning and many nonzero lanes decode as ordinary `f32` values. So the safer current
|
|
read is no longer “maybe a preserved text buffer.” This `0x0e2c..0x0f58` tail is an
|
|
offset-aligned save-side runtime band that overlaps the live outcome-text region in memory but is
|
|
not serialized as the raw `[world+0x4b47]` text payload. The current nonzero save-side content
|
|
continues right up to the first clean field edge at `0x0f58`, after which the next exact grounded
|
|
fields switch to byte and dword lanes with independent semantics. The next
|
|
exact grounded fields after that edge are byte lanes, not restored dwords: `0x0f59` maps to
|
|
`[world+0x4c74]` `Auto-Show Grade During Track Lay`, `0x0f5d` maps to `[world+0x4c78]`
|
|
`Starting Building Density Level`, `0x0f61` maps to `[world+0x4c7c]` `Building Density Growth`,
|
|
`0x0f65` maps to grounded dword `[world+0x4c80]` `leftover simulation time accumulator`, and
|
|
`0x0f6d` maps to byte `[world+0x4c88]` `selected-year lane snapshot`. The write-side owner strip
|
|
for the two building-density fields is explicit now too: the editor page
|
|
`0x004ca910/0x004cb9f0` still owns the ordinary three-state UI path, but the tiny helper family
|
|
`0x004cba34/0x004cba43/0x004cba56/0x004cba69/0x004cba78` also gives direct and fixed-preset
|
|
writes into `[world+0x4c78]` and `[world+0x4c7c]`, with hard-wired low/high helpers for the same
|
|
saved density modes. The selected-year snapshot lane is narrower now too: both
|
|
`world_set_outcome_mode_and_copy_cheat_win_or_loss_status_text` `0x004367c0` and the nonzero
|
|
outcome branch inside `world_apply_compact_runtime_effect_record_to_resolved_targets`
|
|
`0x00431b20` copy current absolute calendar counter `[world+0x15]` into `[world+0x4c88]`, and
|
|
the periodic year-step branch at `0x0040a280` later compares the absolute delta between those two
|
|
lanes against one fixed threshold before it reasserts world flag `[world+0x4d]`. The next later grounded
|
|
field after that is no longer best read as a dword either: `0x0f71` is the first byte of the
|
|
cheat-toggled scenario-lock trio rooted at `[world+0x4c8c..+0x4c8e]`, not the start of one
|
|
independently grounded 4-byte scalar. Current runtime-side evidence only gives one narrower
|
|
consumer inside that trio: `[world+0x4c8e]` is the crash-side global gate already checked by
|
|
`train_trigger_crash_state_effects_and_optional_owner_notifications` `0x004ad7a0`, while
|
|
`0x00437d70` still bounds all three bytes together as cheat-toggled scenario state. The
|
|
frame-side follow-on above the outcome
|
|
prompt is grounded now too: after `0x00436350` stamps `[world+0x4a77]`, internal branch
|
|
`0x0043963d` keeps running only while `[world+0x4a7b]` still matches the current step-local
|
|
marker, then services the queued runtime-effect record family rooted at `[world+0x66a6]`
|
|
through `0x00438710`, conditionally opens `Overview.win` through `0x004f3a10` when the preview
|
|
fixed-record collection at `0x006cea4c` still has one admissible entry, and conditionally opens
|
|
`LoadScreen.win` page `0` through `0x004e4ee0` when shell latch `0x006d4000` is clear and
|
|
world flag `[world+0x4d]` is still nonzero. The same branch also conditionally toggles pause or
|
|
resume through `0x00437a60` when no live multiplayer session object is present at `0x006cd8d8`.
|
|
That splits the outcome prompt owner `0x00436350` cleanly from the later post-transition
|
|
follow-on strip instead of leaving both behaviors folded into one unnamed frame tail. That means
|
|
the simple 4-byte file-lane model
|
|
stops matching grounded live field boundaries immediately after the text-buffer edge: the post-
|
|
`0x0f58` file bytes are still offset-correlated to live state, but they are no longer naturally
|
|
dword-aligned with the next grounded object fields. The new byte-neighborhood probe makes the
|
|
mismatch more concrete. In checked 1.05 scenario saves, the exact grounded byte offsets
|
|
themselves do not look like clean selector values: `p.gms` carries `0x33` at `0x0f5d` and `0x8c`
|
|
at `0x0f6d`, while `q.gms` carries `0xcc` and `0xba` at those same offsets. The only clean
|
|
float-looking starts in that neighborhood instead appear one byte earlier, at `0x0f5c` and
|
|
`0x0f6c`: `p.gms` decodes those as roughly `7.6` and `6.0172`, while `q.gms` decodes them as
|
|
roughly `23.6` and `44.6824`. That tightens the current read further: the checked save bytes
|
|
remain offset-correlated to the live `[world+0x4c74..+0x4c8c]` neighborhood, but they are still
|
|
not a validated byte-for-byte mirror of the exact live field layout. Local
|
|
A second byte-oriented neighborhood immediately after that now has the same kind of split rather
|
|
than a clean restored-field mirror. The earlier grounded anchors in that band all stay zero in
|
|
the checked 1.05 saves: exact file offset `0x0f87` maps to selected-year bucket companion scalar
|
|
`[world+0x4ca2]`, while `0x0f93` and `0x0f97` map to the two startup-owned dwords
|
|
`[world+0x4cae]` and `[world+0x4cb2]`, and the local corpus leaves all three exact dword starts
|
|
zeroed. Those two later dwords are now tight enough in lifecycle to carry conservatively as
|
|
startup-dispatch companion dwords inside the reset-owned late save-visible cluster: the
|
|
already-grounded startup-runtime pre-dispatch helper
|
|
`world_runtime_reset_startup_dispatch_state_bands` `0x004336d0` clears both before
|
|
`shell_active_mode_run_profile_startup_and_load_dispatch` `0x00438890`, the broader
|
|
scenario-state reset owner `0x00436d10` clears them again with the rest of the late save-visible
|
|
cluster, and the post-fast-forward selected-year tail around `0x00437120` clears them one more
|
|
time alongside the shell presenter cache band `[0x006d4024+0x11425a..+0x114276]`. Local static
|
|
evidence still does not show any non-clear readers or nonzero writers for `[world+0x4cae]` or
|
|
`[world+0x4cb2]`, so this pair is closed at the current evidence level as a reset-owned
|
|
structural boundary rather than another active policy or simulation seam. The same is true for
|
|
the later exact byte-owned policy lanes: file offsets `0x0f78`,
|
|
`0x0f7c`, `0x0f7d`, and `0x0f7e` map cleanly to grounded byte fields `[world+0x4c93]` and
|
|
`[world+0x4c97..+0x4c99]`: the linked-site removal follow-on gate plus the three editor
|
|
locomotives-page policy bytes `All Steam Locos Avail.`, `All Diesel Locos Avail.`, and `All
|
|
Electric Locos Avail.`. In the checked 1.05 save corpus those four exact byte lanes all stay
|
|
`0`, which is at least structurally clean. The later grounded dword fields in the same
|
|
neighborhood are less direct again. Exact file offset `0x0f9f` maps to `[world+0x4cba]` (the
|
|
station-list selected-station mirror) and exact offset `0x0fa3` maps to cached
|
|
available-locomotive rating `[world+0x4cbe]`, but the checked save bytes at those exact dword
|
|
starts do not look like clean preserved ids or floats. The only stable float-looking starts sit
|
|
three bytes earlier, at `0x0f9c` and `0x0fa0`: `p.gms` yields roughly `96.8754` and `186.4795`,
|
|
`q.gms` yields `329.9467` and the same `0x0fa0`-side candidate shape, `g.gms` yields `7.0` and
|
|
`95.8507`, and `Autosave.gms` only shows the later `0x0fa0` candidate at about `68.2629`. So
|
|
this later band now has the same conservative read as the post-text one: the save bytes are
|
|
still offset-correlated to grounded live fields, but the exact live byte or dword layout is not
|
|
yet validated as a direct on-disk mirror.
|
|
One more structural cut is now grounded beyond that neighborhood. Under the same offset
|
|
alignment used above, file offset `0x0fa7` maps to the start of the later scenario-state band
|
|
`[world+0x4cc2]`, and `scenario_state_reset_defaults_seed_named_availability_collections_and_rebuild_runtime_bridges`
|
|
`0x00436d10` now explicitly zeroes that late-state band before it separately zero-fills the
|
|
twelve recipe books at `[world+0x0fe7]`. That reset owner is tighter now too: it does not just
|
|
clear one anonymous slab. It first zeroes exactly `0x9b` dwords plus one trailing byte from
|
|
`[world+0x4cc2]`, then separately clears the much larger late runtime slab rooted at
|
|
`[world+0x66be]`, immediately reseeds setup-preview validity byte `[world+0x66be] = 1`,
|
|
reseeds the same editor-owned `Minimum Start Year`, `Default Start Year`, and `Maximum Start
|
|
Year` trio inside that same block at `[world+0x66ca] = 0x726`, `[world+0x66d2] = 0x74e`, and
|
|
`[world+0x66ce] = 0x7d0`, reseeds the four neighboring startup dwords
|
|
`[world+0x6a68/+0x6a6c/+0x6a70/+0x6a74] = 1`, sets the first chairman-slot special occupied-seat
|
|
byte `[world+0x69db] = 1`, and also seeds the same scenario-metadata editor band later consumed
|
|
by `map_editor_scenario_metadata_panel_refresh_controls` `0x004ca790` and rewritten by
|
|
`map_editor_scenario_metadata_panel_handle_message` `0x004cb4a0`, whose write-side body copies
|
|
bounded description and briefing texts into `[world+0x672e/+0x4f30/+0x5ae9]`, flips briefing
|
|
selector `0x621f50`, toggles `[world+0x66de/+0x66f3]`, and reparses the start-year trio with the
|
|
same `1829..2100` clamp plus `minimum <= default <= maximum` normalization, and also
|
|
explicitly resets several already-grounded outcome, rule, and policy
|
|
lanes: the scenario-rule table `[world+0x4a7f..+0x4b3f]` plus trailing scalar `[world+0x4b43]`,
|
|
the outcome-status text root `[world+0x4b47]`, outcome or cheat words `[world+0x4a73/+0x4a77/+0x4a7b]`,
|
|
the queued-event and fast-forward latches `[world+0x46c38/+0x46c3c/+0x66a2/+0x66a6/+0x66aa]`,
|
|
the byte-policy and cached-scalar cluster `[world+0x4c74/+0x4c78/+0x4c7c/+0x4c88/+0x4c8c..+0x4c99/+0x4c9a/+0x4c9e/+0x4ca6/+0x4caa/+0x4cae/+0x4cb2/+0x4cb6/+0x4cba]`,
|
|
and the trailing float strip `[world+0xbce..+0xbf6]` before reseeding its fixed defaults. That
|
|
default reseed is concrete now too: `0x00436d10` restores `[world+0x0be2]` and its live mirror
|
|
`[world+0x0bde]` to `1.0f`, seeds the next four tuning lanes
|
|
`[world+0x0be6/+0x0bea/+0x0bee/+0x0bf2]` to `0x3c75c28f`, and seeds `[world+0x0bf6]` to
|
|
`0x3ba3d70a` before the later selected-year and candidate refresh path runs. The recipe-side
|
|
reset is explicit in the same way: after zeroing exactly `0xea3` dwords rooted at
|
|
`[world+0x0fe7]`, the same owner does not preload one full recipe-book payload table. Instead it
|
|
seeds only the per-book name lane from the fixed format string `# %1` at `0x005c9f78`, using
|
|
generated ordinal strings `1..12` through `0x0051b700 -> 0x00518de0`, before later runtime
|
|
recipe projection re-enters `0x00435630`. That means the reset path itself does not author any
|
|
default line modes, amounts, or cargo-token strings in the later `book+0x3ed/+0x3f1` payload.
|
|
That
|
|
same reset owner is now the strongest current live bridge over the whole later pre-recipe
|
|
plateau:
|
|
after clearing `[world+0x4cc2..+0x4d02]` it rebuilds the named candidate and locomotive
|
|
availability collections, reruns the selected-year adjustment path through
|
|
`0x0051d3f0 -> 0x0051d390 -> 0x00409e80`, refreshes the derived year-threshold side through
|
|
`0x00435603`, reruns candidate filter or visible-count maintenance through `0x0041e970`, and
|
|
refreshes the cached available-locomotive rating through `0x00436af0`, which now reads as a
|
|
year-tiered baseline `110/200/300` plus the strongest surviving live locomotive rating filtered
|
|
by era-policy and named-availability gates, then normalized through the fixed `100/220` scale
|
|
pair and clamped into the final `50..100` cache band at `[world+0x4cbe]`. So the aligned scalar
|
|
plateau `0x0fa7..0x0fe7` now has a stronger boundary than “some bytes before the recipe books”:
|
|
it is the later save-side neighbor immediately in front of a reset-and-rebuild band whose
|
|
downstream consumers are already grounded. Local operand-side evidence is negative in a useful
|
|
way too: after the bulk clear at `0x00436d10`, the current binary does not expose direct
|
|
literal-offset reads or writes for the first dwords in `[world+0x4cc2..]`, so the opening slice
|
|
of that plateau is currently better treated as one reset-owned late-state scalar plateau ahead
|
|
of the recipe books than as a hidden cluster of missed per-field seams. The local layout seam is
|
|
therefore closed at the current evidence level, and the family-level naming is now stable even
|
|
though we still do not have per-dword decodes for most of that opening scalar run. The adjacent
|
|
startup-side special-case gate is
|
|
bounded now too: `0x00436c70` is not another generic late-state scalar helper. It is one
|
|
hard-coded tutorial-signature predicate that only returns true when selector `0x10` is paired
|
|
with the `384x448` map-size check, a live city count of `0x41`, first city name
|
|
`Italy - North`, the current shell-side file/scenario root satisfying `0x4331e0 == 0x16`, and
|
|
row `7` subtype byte `0x6`; the neighboring string table points at `Tutorial_2.gmp`. So this
|
|
branch belongs with the startup/load special-case gates beside the reset owner, not with the
|
|
now-conservatively named `0x4cc2..` late-state scalar plateau itself. The
|
|
serializer-side evidence now sharpens that same boundary too: current local disassembly of
|
|
`0x00446240` writes the leading six-dword tuning band, then falls into the world-grid and
|
|
secondary-raster loops, and only after those loops jumps straight to `[world+0x0fe7]` for the
|
|
recipe books. So the plateau is still a real save/load family, but not one direct serializer
|
|
block in the same way as the recipe books or the scenario-rule band. The earlier
|
|
late-state cluster is tighter now too: `[world+0x4c9a]` and `[world+0x4c9e]` are no longer just
|
|
save-side counters in the reset slab. The support family at `0x0062b244` actively maintains them
|
|
as two nonnegative live-entry counters through
|
|
`support_collection_try_spawn_goose_entry_in_primary_counter_lane` `0x0040b0b0`,
|
|
`support_collection_select_or_spawn_goose_entry_id` `0x0040b2d0`, and
|
|
`support_collection_release_entry_and_decrement_world_type_counters` `0x0040af00`. The paired
|
|
float lanes `[world+0x4ca6/+0x4caa]` are tighter in the same way: `0x0041144f` accumulates live
|
|
deltas into pending lane `+0x4caa`, `scenario_state_roll_pending_float_0x4caa_into_accumulator_0x4ca6`
|
|
`0x00433f02` rolls that pending value into accumulator `+0x4ca6`, and the shell-side query lane
|
|
at `0x0042f89b/0x0042f8bb` reads both the pending-only and accumulated sums. `[world+0x4cb6]`
|
|
is also no longer an anonymous save byte or dword: the shell-side `TrainList.win` family rooted
|
|
at `0x006d3b34` actively mirrors the current selected train-side support-entry id there. The
|
|
constructor `shell_train_list_window_construct` `0x00515f50` seeds the singleton and wires the
|
|
top list controls `0x32c9/0x32ca`; the refresh owner
|
|
`shell_train_list_window_refresh_controls` `0x005158f0` reselects `[world+0x4cb6]` when that id
|
|
still resolves to one live train owned by the current company; and the message owner
|
|
`shell_train_list_window_handle_message` `0x00515c60` mirrors top-list picks and direct payloads
|
|
back into `[world+0x4cb6]` before republishing focus through `0x00433900` and the detail-panel
|
|
transition manager. The earlier helper writes at `0x00514b0e`, `0x00515d14`, and `0x00515f40`
|
|
now sit cleanly inside that same train-list selection seam. The smaller callback strip under the
|
|
same family is grounded too: `0x005157e0` exposes the current top-side latch `0x006d3b30`,
|
|
`0x00515780` preserves the lower action range `0x332c..0x36b0` only while the event still
|
|
targets the active top list, `0x005157f0` is the shared top-list train-row summary renderer over
|
|
`0x004bd4a0`, `0x00515820` is the focus-and-follow callback that republishes a selected train id
|
|
into the shell detail controller and can recenter the world through the linked route object, and
|
|
`0x005158b0` is the inactive-side lower-row refresh callback into `0x004bf320`.
|
|
`[world+0x4cba]` is tighter in the same way now: it is the shared selected station id mirrored
|
|
by the shell-side station-list and station-detail families, not just another save-visible late
|
|
dword in the reset slab. `shell_station_list_window_refresh_rows_selection_and_status`
|
|
`0x00506f30` restores `[world+0x4cba]` into the paired row controls `0x61a9/0x61aa` when that
|
|
id still resolves to one live current-company station; `shell_station_list_window_handle_message`
|
|
`0x005071e0` mirrors direct top-list row activations and side-picker results back into the same
|
|
latch before optional recentering and detail-panel transition; and `shell_station_detail_window_handle_message`
|
|
`0x00505e50` mirrors the current detail-manager station into `[world+0x4cba]` on setup. The
|
|
earlier writes at `0x0050727a` and `0x005072cd` therefore now sit cleanly inside the same
|
|
station-list selection seam rather than pointing to a separate late-state owner.
|
|
The neighboring bytes `[world+0x4c90/+0x4c91/+0x4c92]` are narrower now too, but only in the
|
|
negative sense: the current binary still shows no grounded non-reset readers or writers for
|
|
those three one-byte lanes. In local static evidence they only appear in the shared
|
|
scenario-state reset-and-rebuild owner `0x00436d10`, which clears them alongside the broader
|
|
late-state cluster before the later selected-year, availability, and recipe-runtime rebuilds.
|
|
So the strongest current read is that they remain reset-only late-state bytes, not yet another
|
|
live shell or simulation seam.
|
|
The earlier
|
|
persisted six-dword tuning band should now
|
|
be kept separate from that later slab rather than folded into the same “pre-recipe plateau”
|
|
label. The editor and runtime bridge is tighter now too: the shell-side
|
|
economic tuning owner `0x004ca980/0x004cadf0` writes the visible slider values directly into
|
|
`[world+0x0be2/+0x0be6/+0x0bea/+0x0bee/+0x0bf2/+0x0bf6]` and mirrors the first lane into
|
|
`[world+0x0bde]`; the write path is asymmetric too, because lane `0` uses its dedicated divisor
|
|
at `0x005c85d8` while the trailing five lanes share the centered `(value-0xce)/0x005c87f8`
|
|
path. The `.smp` save/load pair persists that same six-dword band; the post-load generation
|
|
pipeline `0x004384d0` reseeds `[world+0x0bde]` from `[world+0x0be2]`, runs the preliminary
|
|
candidate-availability prepass `0x00437737(0)` on setup calls, and only then enters its visible
|
|
`318/320/321/319/322` progress lanes. `world_region_query_projected_structure_count_scalar_by_category`
|
|
`0x004234e0` consumes `[world+0x0bde]` as one global multiplier on both its live-region and
|
|
fallback projected-structure branches, but the branch split is tighter now too: only the
|
|
live-region side also multiplies by cached building-count slot `[region+0x242]`, while the
|
|
fallback side swaps to alternate difficulty table `0x005f33cc` and omits that count multiplier
|
|
entirely. The same post-load owner is tighter on its gated setup phases too: if shell-state gate
|
|
`[0x006cec74+0x174]` is live while master editor-mode latch `[0x006cec74+0x68]` stays clear, it
|
|
marks one-shot latch `[world+0x46c3c] = 1`, runs `0x00421c20(1.0, 1)`, and then clears that
|
|
latch again; if `[0x006cec74+0x178] > 0` under the same editor-mode clear gate it follows with
|
|
`simulation_run_chunked_fast_forward_burst` `0x00437b20`. The `319` lane is tighter in the same
|
|
way: when startup latch `0x006cd8d8` is clear it stamps `[0x006cec7c+0x79] = 1`, ensures
|
|
`[world+0x6a6c] >= 1`, forces chairman-seat byte `[world+0x69db] = 1`, and then re-enters
|
|
`0x004377a0` before the later route-entry and placed-structure refresh families. The
|
|
region-side setup branches are narrower in the same negative way now too: `0x00421c20` is just
|
|
the collection dispatcher, and its worker `0x004235c0` stays inside live region demand and
|
|
placement by routing through `0x00422900` cached category accumulation, `0x004234e0` projected
|
|
structure-count scalars, `0x00422be0` placed-count subtraction, and `0x00422ee0` placement
|
|
attempts over the live placed-structure registry `0x0062b26c`. Likewise the `321` tail
|
|
`0x00437b20 -> 0x00423d30` only refreshes cached category slots
|
|
`[region+0x27a/+0x27e/+0x282/+0x286]` through `0x00422900`. So these post-load branches stay
|
|
ruled down as setup and cache-maintenance work rather than the missing restore-time republisher
|
|
for `[region+0x2a4]` or `[region+0x310/+0x338/+0x360]`.
|
|
The surrounding `319` helpers are narrower in the same negative way now too: `0x00437220` and
|
|
`0x004377a0` stay on chairman-slot selector and profile materialization over
|
|
`[world+0x69d8/+0x69db]` and scenario selector bytes `[0x006cec7c+0x87]`, while `0x00434d40`
|
|
only seeds the subtype-`2` candidate runtime latch `[candidate+0x7b0]` across live placed
|
|
structures. That leaves the placed-structure replay strip `0x004133b0` as the only region-
|
|
adjacent bridge inside the `319` plateau worth chasing for the missing restore seam.
|
|
The
|
|
editor-side read path is explicit on the same seam:
|
|
`map_editor_economic_cost_panel_refresh_preview_curve_and_numeric_rows` `0x004caaf0` reads the
|
|
same six-float band, builds the live preview curve on control `0x5be1`, and republishes the six
|
|
numeric value rows through controls `0x5bce/0x5bd0/0x5bd2/0x5bd4/0x5bd6/0x5bd8`, so the panel is
|
|
now grounded as a full read/write save-state owner rather than only a slider mutator. The
|
|
neighboring `Cities/Regions` editor page is now a second grounded live consumer instead of just a
|
|
page-local constructor: `map_editor_city_region_panel_format_selected_region_detail_stats_and_projected_building_rows`
|
|
`0x004cc340` reads the same leading tuning lanes `[world+0x0be2/+0x0be6/+0x0bea/+0x0bee]` while
|
|
it formats the selected region detail card and projected/live structure rows through
|
|
`0x00422900` and `0x004234e0`. The
|
|
recurring maintenance side is grounded too:
|
|
`simulation_service_periodic_boundary_work` `0x0040a590` derives one bounded bucket from the
|
|
selected-year gap, reads the corresponding float from the five-slot table
|
|
`[world+0x0be6/+0x0bea/+0x0bee/+0x0bf2/+0x0bf6]`, and folds that result back into the running
|
|
scalar `[world+0x0bde]` before its company/profile refresh sweep. Its aligned dword run now
|
|
splits cleanly by
|
|
save family. The
|
|
base 1.05 saves (`Autosave.gms`, `nom.gms`) carry one stable signature with
|
|
`0x0faf = 0x8000003f`, `0x0fb3 = 0x75c28f3f`, repeated `0x75c28f3c` lanes through `0x0fbf`, a
|
|
sign-flipped lane `0x0fc3 = 0xa3d70a3c`, one tiny marker at `0x0fc7 = 0x0000003b`, and
|
|
`0x0fcb = 0x00300000`. The scenario-save family (`p.gms`, `q.gms`) carries a different stable
|
|
plateau over the same offsets, beginning `0x0faf = 0x4000003f`, `0x0fb3 = 0xe560423f`, then
|
|
`0x03126f3b`, `0x1374bc3c`, and paired `0x23d70a3c` lanes at `0x0fbf/0x0fc3`, with
|
|
`0x0fc7 = 0x0000003c`. The alt-save family (`g.gms`) follows the base signature through
|
|
`0x0fc7`, then diverges sharply into the same `0xcdcdcd..` fill pattern already seen in its
|
|
earlier header lanes. So the current best fit for `0x0fa7..0x0fe7` is a family-shaped aligned
|
|
scalar plateau that belongs to save-side runtime state and terminates immediately before the
|
|
grounded recipe-book block, not one more directly named live-field mirror. One conservative
|
|
loader-side summary probe now starts exactly at that recipe root instead of extending the plateau
|
|
model further. The fixed recipe-book block spans twelve books from `0x0fe7` with stride `0x4e1`,
|
|
and the checked map/save pairs `Alternate USA.gmp -> Autosave.gms`, `Southern Pacific.gmp ->
|
|
p.gms`, and `Spanish Mainline.gmp -> g.gms` preserve that rooted block byte-for-byte in the
|
|
sampled local corpus. The current probe therefore treats it as preserved scenario payload rather
|
|
than save-only runtime drift and reports the same structural shape the `.smp` owners use: one
|
|
`book+0x3ed` annual-production dword, one `0x3d`-byte book header, and five repeated
|
|
`0x30`-byte cargo-line tuples rooted at `book+0x3f1`, each with mode dword `+0x00`,
|
|
annual-amount dword `+0x04`, supplied-token dword window `+0x08`, and demanded-token dword
|
|
window `+0x1c`. That is enough to separate zero, `0xcd`-filled, and mixed books or lines
|
|
without overstating line semantics beyond the grounded editor/runtime ownership already
|
|
documented below.
|
|
Local
|
|
corpus clustering now makes the remaining split more specific. The base 1.05 save family
|
|
(`Autosave.gms`, `nom.gms`) shares a narrow tail-heavy subset with stable relative offsets
|
|
`0xec`, `0xf8`, `0x118`, `0x134`, and `0x138`, while still varying in value across files. The
|
|
1.05 scenario-save family (`p.gms`, `q.gms`) shares a much broader stable set spanning almost the
|
|
whole window from `0x04` through `0x134`, again with per-file scalar differences but consistent
|
|
occupancy. Pairwise compare runs tighten that read further: `Autosave.gms` vs `nom.gms` does not
|
|
preserve one common numeric tail signature even at the shared base-save offsets, and `p.gms` vs
|
|
`q.gms` keeps the broad scenario-save occupancy pattern but still changes every shared value, with
|
|
`q.gms` additionally lighting two extra lanes at `0x78` and `0x84`. So the current best fit is
|
|
“family-shaped live scalar state” rather than family-default constants. The lone 1.05 alt-save
|
|
sample (`g.gms`) only lights up four lanes at `0x58`, `0x6c`,
|
|
`0x128`, and `0x12c`. The checked 1.05 maps and classic saves stay zero in that same bounded
|
|
window, which strengthens the current read that this is runtime-save scalar state rather than
|
|
generic map payload. One older unknown map-family outlier in the local corpus does still carry a
|
|
populated window: `Tutorial_2.gmp` under the classic install tree. So the safest current note is
|
|
“zero for grounded map families and classic save families, nonzero for observed 1.05 save
|
|
families, with one older unknown-map exception.” Static consumer grounding is still sparse for
|
|
that tail: direct object-offset hits currently only name the trailing scalar `[world+0x4b43]`
|
|
through the editor panel and `.smp` save or restore family, while local opcode searches do not
|
|
yet surface equally direct reads for the intervening `+0x4b0b..+0x4b3f` tail lanes. So the
|
|
save-file family clustering is now strong enough to close the load/save seam at the current
|
|
evidence level: those later tail scalars are one bounded post-sentinel special-condition save
|
|
tail rather than a hidden extra serializer family. Individual dwords inside that tail still lack
|
|
per-lane decodes, but the family-level name is now stable. The
|
|
same branch is no longer world-entry-only either: current local
|
|
disassembly now shows the identical lane-adjust and
|
|
`0x51d3f0 -> 0x51d390 -> 0x409e80` sequence in the post-fast-forward selected-year tail inside
|
|
`scenario_state_reset_defaults_seed_named_availability_collections_and_rebuild_runtime_bridges`
|
|
`0x00436d10`, which lines up with the existing post-fast-forward callers already mapped under
|
|
`world_refresh_selected_year_bucket_scalar_band` `0x00433bd0`,
|
|
`scenario_state_ensure_derived_year_threshold_band` `0x00435603`,
|
|
`structure_candidate_collection_refresh_filter_and_year_visible_counts` `0x0041e970`, and
|
|
`scenario_state_refresh_cached_available_locomotive_rating` `0x00436af0`. The selected-year
|
|
companion itself is tighter now too: `0x00433bd0` picks one scalar from the fixed 21-entry year
|
|
ladder, seeds direct bucket lanes `[world+0x65/+0x69/+0x6d]`, then rebuilds the dependent
|
|
complement trio `[world+0x71/+0x75/+0x79]` and the later scaled companion trio
|
|
`[world+0x7d/+0x81/+0x85]` from that same source after the build-version-sensitive clamp through
|
|
`0x00482e00(0x006cec74)`. That restore now
|
|
also has some neighboring slot semantics bounded well enough to carry in the loader notes. Slot
|
|
`31` `[0x006cec78+0x4afb]` is no longer best read as an unnamed runtime cargo-economy latch:
|
|
local disassembly now ties it directly to the saved special-condition table entry `Use Wartime
|
|
Cargos`, and the strongest current runtime owner is
|
|
`structure_candidate_collection_refresh_cargo_economy_filter_flags` `0x0041eac0`. Inside that
|
|
candidate-collection sweep the wartime-cargo branch only activates when slot `31` is set and
|
|
then treats the string family `Clothing`, `Cheese`, `Meat`, `Ammunition`, `Weapons`, and
|
|
`Diesel` as one special cargo set before writing the live candidate filter byte `[entry+0x56]`.
|
|
That makes the old read-side note around `0x00412560` tighter too: the neighboring descriptor
|
|
gate is now best understood as using the live copy of the `Use Wartime Cargos` scenario rule,
|
|
the live cargo-availability latch at `[cargo+0x16e]`, and the paired selected-bank dword gates
|
|
`[desc+0x24/+0x28]`, not an anonymous cargo-economy mode byte. Slot `34` `[0x006cec78+0x4b07]`
|
|
is similarly bounded
|
|
on the runtime side:
|
|
`world_run_company_start_or_city_connection_chooser_with_region_field_0x2d_temporarily_cleared_if_rule_0x4b07`
|
|
`0x004013f0`, which sits immediately above the broader company-start or city-connection chooser
|
|
`0x00404ce0`, snapshots region dword `[entry+0x2d]` across all `0x18` live region records in
|
|
`0x006cfc9c`, zeros that field while the chooser runs, and then restores the original values on
|
|
exit. The chooser-side effect is now the useful grounded part: the same owner normally uses
|
|
`[region+0x2d]` as one per-region exclusion gate while building startup or city-connection
|
|
candidates, so slot `34` effectively suppresses that exclusion latch during the startup pass
|
|
without needing a stronger semantic name for the field itself. Slot `29` `[0x006cec78+0x4af3]`
|
|
is less semantically tidy but still worth carrying
|
|
as a bounded consumer family: the placed-structure-side radial class-`2` stamp path only
|
|
activates when that slot is nonzero and the linked candidate or era record at `[entry+0x41]`
|
|
equals `5`, while two already-grounded world helpers
|
|
`world_stamp_radial_secondary_raster_class_2_marks_from_world_coords` `0x0044e7d0`,
|
|
`world_scan_secondary_grid_marked_cell_bounds` `0x0044ce60` and
|
|
`world_service_secondary_grid_marked_cell_overlay_cache` `0x0044c670` also gate on the same
|
|
slot. So the identity of slot `29` as saved rule data is grounded, but the downstream runtime
|
|
semantics are still mixed enough that the loader should preserve the raw value without trying to
|
|
rename its whole consumer family yet. The neighboring train-safety slots are now bounded enough
|
|
to keep as a cautious runtime split too. Slot `33` `[0x006cec78+0x4b03]`
|
|
`Disable Train Crashes AND Breakdowns` is the coarse gate inside
|
|
`train_service_try_trigger_crash_or_breakdown_from_year_and_load_thresholds` `0x004af8a0`: the
|
|
very first slot-`33` gate jumps straight
|
|
to the function tail when the slot is set, bypassing the year-scaled threshold build, the later
|
|
random or threshold comparison, and the two follow-on state transitions at `0x004ad7a0` and
|
|
`0x004ada00`. Slot `32` `[0x006cec78+0x4aff]` `Disable Train Crashes` is narrower in the same
|
|
family: after the threshold path has already run, the later slot-`32` gate uses slot `32` to
|
|
suppress only the lower failure-transition path and force the milder follow-on at `0x004ada00`.
|
|
That same slot-`33` read also appears in
|
|
`train_query_deterioration_scalar_with_disable_bypass` `0x004ac460`, where setting it returns
|
|
one fixed float immediately before the ordinary route-object-dependent calculation runs. So the
|
|
current best loader-facing read is: slot `33` is the broad train deterioration bypass, while slot
|
|
`32` matches its loader-facing label directly as the narrower `Disable Train Crashes` gate inside
|
|
the same family, suppressing only the crash transition while leaving the breakdown branch live.
|
|
That restore now
|
|
also has one concrete file-side correlation in the classic `.gms` family: local save inspection
|
|
now consistently finds `0x32dc` at `0x76e8`, `0x3714` at `0x76ec`, and `0x3715` at `0x77f8` in
|
|
`Autosave.gms`, `kk.gms`, and `hh.gms`, leaving one exact `0x108`-byte span from `0x76f0` to
|
|
`0x77f8` between `0x3714` and `0x3715`. That span already carries staged-profile-looking payload
|
|
text such as `British Isles.gmp`, so the current static-file evidence now supports the atlas-side
|
|
`0x108` packed-profile note for the classic save family as another serialized setup-profile slab,
|
|
not an unrelated anonymous save trailer. The same classic corpus is tighter now too: the leading payload
|
|
boundary is slightly skewed relative to the simple `0x76f0` chunk cut, which is why the classic
|
|
map-path C string first becomes visible at relative offset `0x13` and the display-name string at
|
|
`0x46` instead of the cleaner `0x10/0x43` split seen in the 1.05 branch. Outside that skewed
|
|
front edge the block is otherwise almost entirely zeroed, and the three local samples are
|
|
byte-identical except for the leading dword at `+0x00` (`3` in `Autosave.gms` and `hh.gms`,
|
|
`5` in `kk.gms`). One middle strip in that classic block is now exact too: all three checked
|
|
saves carry the same fixed bytes `+0x79..+0x8a = 25 07 01 00 01 00 01 00 00 00 00 00 da 33 00 00 01 65`.
|
|
The currently atlas-tracked bytes `[profile+0x77]`, `[profile+0x82]`,
|
|
`[profile+0x97]`, and `[profile+0xc5]` are all `0` in that classic sample set, so the current
|
|
file-side evidence now supports a stronger boundary than the older “field layout unresolved” note:
|
|
the classic slab preserves the same staged-profile string core and the same middle-band setup
|
|
structure, but in the checked classic saves the branch-driving launch/campaign latches stay zero
|
|
and most surrounding bytes remain empty. So the local static seam is closed here too: this is the
|
|
same serialized setup/runtime profile family, with the classic-only extras carried
|
|
conservatively as the fixed middle strip and the skewed front-edge framing. One 1.05-era
|
|
file-side analogue is now
|
|
visible too, but only as an inference from repeated save structure rather than a disassembly-side
|
|
field map: local `.gms` files in `rt3_105/Saved Games` carry one compact string-bearing block at
|
|
`0x73c0` with the same broad shape as the classic profile slab, including a leading dword at
|
|
`+0x00`, one map-path string at `+0x10`, one display-name string at `+0x43`, and a middle strip
|
|
around `+0x76..+0x88` that is now more specific than the earlier generic “small nonzero tail”
|
|
note. Across all five checked 1.05 saves, the compact slab keeps `+0x77 = 0x07`, `+0x78 = 0x01`,
|
|
`+0x7c = 0x01`, `+0x86 = 0x01`, and `+0x87 = 0x65`, while the scenario-sensitive pair
|
|
`+0x82/+0x83` varies coherently as `0x4d/0x36` for `Alternate USA`, `0x90/0x1b` for
|
|
`Southern Pacific`, and `0xa3/0x29` for `Spanish Mainline`. One narrower scenario-save split is
|
|
visible inside that same strip too: the checked scenario saves `p.gms` and `q.gms` also carry
|
|
`+0x7a = 0x05` and the extra four-byte band `+0x88..+0x8b = 66 67 68 69`, while the other
|
|
checked 1.05 saves leave those lanes zeroed. Relative `+0x97` and `+0xc5` still remain `0`.
|
|
The compared 1.05 save set is tighter now too:
|
|
`Autosave.gms` and `nom.gms` cluster together on `Alternate USA.gmp` with `+0x82 = 0x4d`,
|
|
`g.gms` carries `Spanish Mainline.gmp` with `+0x82 = 0xa3`, and `p.gms`/`q.gms` cluster on
|
|
`Southern Pacific.gmp` with `+0x82 = 0x90`; across all five files the same inferred analogue
|
|
lane at `+0x77` stays fixed at `0x07`, while the same map- or scenario-sensitive tail word at
|
|
`+0x80` tracks those `0x4d/0xa3/0x90` byte lanes (`0x364d0000`, `0x29a30000`, `0x1b900000`).
|
|
The leading dword at `+0x00` also splits the same corpus, with `Autosave.gms` alone at `3` and
|
|
the other four checked 1.05 saves at `5`. That is enough to say the wider save corpus does
|
|
contain nonzero candidates for two of the already-grounded profile lanes: `+0x77` is still the
|
|
selected-year lane from the setup/runtime profile family, and `+0x82` is at least the same
|
|
sandbox-launch anchor used by later `Setup.win` launch branches. The current corpus also shows
|
|
that one of those grounded lanes, `+0x82`, varies coherently with the loaded scenario family.
|
|
The same setup/runtime profile family now bounds more of the compact slab than before too:
|
|
`runtime_profile_reset_default_setup_and_campaign_seed_fields` `0x0047bbf0` seeds
|
|
`[profile+0x79] = 1`, `[profile+0x7b] = 0`, clears `[profile+0x82]`, writes one bounded
|
|
random-like dword into `[profile+0x83]`, seeds the first setup row-marker byte
|
|
`[profile+0x87] = 1`, and forces the file-backed launch or rehydrate latch `[profile+0x97] = 1`;
|
|
`shell_setup_profile_copy_payload_scroll_count_and_campaign_byte_and_seed_row_categories`
|
|
`0x0047be50` then copies payload lanes into `[profile+0x77/+0x79/+0x7b/+0xc5]`; and the broader
|
|
setup-mode owner `shell_setup_window_select_launch_mode_and_apply_shell_state` `0x00502c00`
|
|
treats `[profile+0x97]` as the file-backed launch or rehydrate latch, `[profile+0x82]` as the
|
|
sandbox-side launch byte, and its dataset-backed row-selection lane now grounds the staged
|
|
presence byte `[profile+0x10]` plus the paired `0x32`-byte file/path bands at
|
|
`[profile+0x11]` and `[profile+0x44]`. The neighboring setup-side consumer note is tighter now
|
|
too: `map-and-scenario-content-load.md` already grounds `[profile+0x79]` as the live-row
|
|
threshold lane used by the payload-row draw callback and `[profile+0x7b]` as the current scroll
|
|
or row-index lane adjusted by controls `0x0ce6/0x0ce7`. The current file-side 1.05 corpus now
|
|
supports a stronger boundary than the earlier wider-layout note: this compact slab is
|
|
not a byte-for-byte dump of the staged `0x108`-byte runtime profile, but a closely related
|
|
serialized profile payload with a grounded setup core. The direct core lanes match the staged
|
|
profile family (`+0x77`, `+0x79`, `+0x7b`, `+0x82`, `+0x87`, `+0x97`, `+0xc5`, and the paired
|
|
`+0x10/+0x43` string bands), while the stable presence byte at `+0x0f`, the leading dword at
|
|
`+0x00`, the scenario-sensitive middle word around `+0x80`, and the scenario-save-only
|
|
`+0x88..+0x8b = 66 67 68 69` band show that the save slab also carries file-format-specific
|
|
staging beyond the runtime profile core. The setup-side payload loader is tighter on the same
|
|
seam now too: `shell_setup_load_selected_profile_bundle_into_payload_record` `0x00442400` does
|
|
not load one single canonical payload shape. In the ordinary saved-profile lane it reads one
|
|
small startup payload dword through the ordinary tag-`1` family, then one raw `0x03c2` preview
|
|
block, and expands that byte surface into packed `ARGB` dwords rooted at `payload+0x03c2`. That
|
|
same ordinary-profile dword is also
|
|
stored into shared global `0x00620e94`, which later reappears in the early and late world-entry
|
|
threshold gates. In the map-style lane `0x00442400` instead restores the larger setup payload
|
|
family under `0x2ee0/0x2ee1`, and current local disassembly now makes the split explicit: this
|
|
tagged map-style branch does not perform the `0x00620e94` store at all. Bundle versions
|
|
`>= 0x3f7` restore the full `0x403c2`-byte setup-preview payload record, while older bundles
|
|
only restore `0x402c9` bytes and explicitly zero the trailing `0x1003e`-byte tail at
|
|
`payload+0x2c9`. That keeps the setup payload family aligned with the later live world block
|
|
`[world+0x66be]` without overstating it as one uniform file layout across all setup/profile
|
|
sources. The current ownership boundary is tighter now too: a direct full-binary xref sweep only
|
|
turns up the already-grounded two direct writers to `0x00620e94`, namely the ordinary saved-profile
|
|
path in `0x00442400` and the package-save prelude seed `0x00444dd0 = 0x26ad`; `0x00441ec0` only
|
|
snapshots that dword into the transported sidecar strip, while `0x00437737` and `0x00444dc5`
|
|
only compare against it.
|
|
framing and scenario-family metadata around that shared setup core. So the local static seam is
|
|
closed here: those grounded lanes belong to one serialized setup-profile slab, while the
|
|
surrounding extra bytes now carry conservative framing names rather than reading as stray runtime
|
|
fields. The leading dword is the serializer-tag lane, `+0x0f` is the stable presence byte, the
|
|
classic branch has one skewed front edge plus one fixed middle strip, the 1.05 middle word around
|
|
`+0x80` is the scenario-sensitive profile-framing lane, and `+0x88..+0x8b` is the
|
|
scenario-save-only extra band. The loader-side
|
|
family split is tighter now too: `p.gms` and `q.gms` no longer live under a generic fallback;
|
|
their save headers now classify as one explicit `rt3-105-scenario-save` branch with preamble
|
|
words `0x00040001/0x00018000/0x00000746` and the early secondary window
|
|
`0x00130000/0x86a00100/0x21000001/0xa0000100`, while `g.gms` now classifies as a second
|
|
explicit `rt3-105-alt-save` branch with the different preamble lane
|
|
`0x0001c001/.../0x00000754` and early window
|
|
`0x00010000/0x49f00100/0x00000002/0xa0000000`. That branch now carries the same bootstrap,
|
|
anchor-cycle, named 1.05 trailer, and narrow profile-block extraction path as the other 1.05
|
|
saves. The bridge just below that trailer is now explicit too: the common 1.05 save branch
|
|
carries selector/descriptor `0x7110 -> 0x7801` in `Autosave.gms` and `0x7110 -> 0x7401` in
|
|
`nom.gms`, and both still reach the same first later candidate at
|
|
`span_target + 0x189c`, well before the packed profile at `span_target + 0x3d48`; the
|
|
`rt3-105-alt-save` branch instead carries `0x54cd -> 0x5901` and its first later candidate
|
|
lands at `packed_profile + 0x104`, essentially on the profile tail; the scenario-save branch
|
|
still diverges locally with `0x0001 -> 0x0186` and never enters that later `0x32c8`-spanned
|
|
bridge at all. The common-branch bridge payload is narrower now too: both checked base saves
|
|
expose the same 0x20-byte primary block at `0x4f14` followed by the same denser secondary block
|
|
at `0x671c`, `0x1808` bytes later, and that secondary block now appears to run intact up to the
|
|
packed-profile start at `0x73c0` for a total observed span of `0xca4` bytes. The trailing slice
|
|
of that secondary block is now typed one level further: a small header at `secondary+0x354`
|
|
carries the observed stride `0x22`, capacity `0x44`, and count `0x43`, followed by a fixed-width
|
|
67-entry name table starting at `secondary+0x3b5` and running through names like
|
|
`AluminumMill`, `AutoPlant`, `Bakery`, `Port00..11`, and `Warehouse00..11`, with a short footer
|
|
(`dc3200001437000000`) after the last entry. The trailing per-entry word is now surfaced too:
|
|
most entries carry `0x00000001`, while the currently observed zero-trailer subset is
|
|
`Nuclear Power Plant`, `Recycling Plant`, and `Uranium Mine`. That footer is tighter now too:
|
|
it parses directly as `0x32dc`, `0x3714`, and one trailing zero byte, so the shared
|
|
map/save catalog currently ends on the same two grounded late-rehydrate progress ids that the
|
|
classic staged-profile band already exposed. The strongest structural read is therefore that the
|
|
entire `0x6a70..0x73c0` catalog region is shared verbatim between `Alternate USA.gmp` and the
|
|
derived `Autosave.gms`, not rebuilt independently during save. Combined with the earlier
|
|
grounded record-layout work under `0x00437737`, `0x00434ea0`, and `0x00434f20`, the current
|
|
safest semantic read is that this shared catalog is the bundled source form of the scenario-side
|
|
named candidate-availability table later mirrored into `[state+0x66b2]`, with each entry's
|
|
trailing dword now reading as the same availability override bit later copied into
|
|
`[candidate+0x7ac]`. The candidate-side refresh strip is tighter now too: `0x00412c10` walks
|
|
the live candidate pool, forces `[candidate+0x7ac] = 1` whenever availability bytes
|
|
`[candidate+0xba/+0xbb]` are already set or subtype `[candidate+0x32]` is not `2`, and only for
|
|
the remaining subtype-`2` records does it consult `0x00434ea0` by stem before tailing into the
|
|
dependent cargo-economy filter rebuild `0x0041eac0`. The adjacent collection helpers also read
|
|
cleanly now: `0x00412bd0` is the collection-wide `0x00411ee0` cargo-summary rebuild sweep over
|
|
imported `0xbc` descriptor arrays, explicitly rebuilding the two compact cargo-membership tables
|
|
`[candidate+0x79c/+0x7a0]`, their counts `[candidate+0x7a4/+0x7a8]`, and the scaled runtime rate
|
|
band `[candidate+0xa1..+0xb8]`, while `0x00412ba0` is the remove-and-release sibling that clears
|
|
one candidate's dependent runtime descriptor and cargo-membership tables through `0x00411cb0`
|
|
before erasing that id from the pool. One lower runtime detail is explicit now too:
|
|
`0x00411ee0` does not just “refresh summary tables.” It rebuilds the two emitted cargo-id tables
|
|
at `[candidate+0x79c]` and `[candidate+0x7a0]` from one temporary `0x35`-cargo mark band, stores
|
|
their counts at `[candidate+0x7a4]` and `[candidate+0x7a8]`, and accumulates the scaled runtime
|
|
rates into `[candidate+0xa1..+0xb8]`; mode-`0` descriptor rows use the shared production cap at
|
|
`[candidate+0x2a]` divided by the descriptor amount, while nonzero mode rows bypass that cap
|
|
scaling. The shared reset side is explicit now too: `0x00436d10` is the scenario-state
|
|
reset-and-rebuild owner beneath startup and world-entry. It zeroes the late scenario-state bands,
|
|
seeds the fixed minimum/default/maximum start-year trio and chairman-slot rows, reseeds the same
|
|
six-dword economic-tuning
|
|
band later serialized at `0x00446240`, restored at `0x00446d40`, and edited through
|
|
`0x004ca980/0x004caaf0/0x004cadf0`, rebuilds the two named-availability collections at
|
|
`[state+0x66b2]` and `[state+0x66b6]`, zero-fills the twelve recipe books at `[state+0x0fe7]`,
|
|
then only re-seeds their per-book name lane from the fixed `# %1` format string at `0x005c9f78`.
|
|
Its selected-year import tail is explicit now too: in the campaign/setup-but-not-sandbox lane it
|
|
copies profile year word `[profile+0x77]` into scenario default start year `[state+0x66d2]`,
|
|
seeds the
|
|
Jan-1 tuple lanes `[state+0x05/+0x09]` through `0x0051d3f0`, conditionally decrements that chosen
|
|
year through the shell/tutorial gates at `[0x006cec74+0x68/+0x178]` and `[0x006cec78+0x4af7]`,
|
|
and only then rebuilds the absolute selected-year counter through `0x0051d390 -> 0x00409e80`,
|
|
the selected-year bucket band through `0x00433bd0`, the derived year-threshold band through
|
|
`0x00435603`, and the year-gap scalar helper `0x00434130`, which now reads more tightly as a
|
|
two-stage bridge that first stores one current-year-minus-1850 normalized float into
|
|
`[world+0x4ca2]` and then immediately reclamps that same field into the closed `1/3..1.0`
|
|
band by flooring sub-threshold values to literal `0.333333...` and capping larger values at
|
|
`1.0`. Only after that
|
|
selected-year and
|
|
calendar chain does it re-enter `0x00435630`, `0x0041e970`, `0x00412bd0`, and `0x00436af0`. The loader-side coverage
|
|
around world entry is tighter now too. `0x00443a50` does not just “restore the late profile
|
|
block” after the tagged collections load: it re-enters `0x00436d10`, restores the late
|
|
setup-preview payload block `[world+0x66be]` from `0x2ee0/0x2ee1`, immediately re-normalizes that
|
|
payload through
|
|
`shell_setup_payload_seed_unique_row_category_bytes_and_marker_slots` `0x0047bc80`, reloads the
|
|
`0x108`-byte profile block, mirrors the campaign/setup byte
|
|
`[profile+0xc5]` and sandbox launch byte `[profile+0x82]` into `[world+0x66de/+0x66f2]`,
|
|
restores `[profile+0x77]` into the selected-year lanes, reruns
|
|
`0x00409e80`, `0x00433bd0`, `0x00435603`, `0x00444dc5`, `0x0041e970`, `0x00412bd0`,
|
|
`0x00434130`, and `0x00436af0`, and only then rehydrates `[world+0x66b2]`, `[world+0x66b6]`,
|
|
and the later locomotive override refresh `0x00461e00`. That named-availability restore split is
|
|
tighter now too: the candidate side keeps only rows whose copied names survive the built-in stem
|
|
rejects and still resolve into the live candidate pool, with no later fallback preseed if that
|
|
validated pass stays empty, while the locomotive side bulk-reinserts its fixed `0x41`-byte rows
|
|
raw and only then falls back to `0x004350b0` if the collection is still empty. The loader-side
|
|
coverage is tighter now too:
|
|
the same table parser now
|
|
attaches both to the common-save bridge payload and directly to the fixed source range in
|
|
`.gmp` files and the non-common `rt3-105-scenario-save` / `rt3-105-alt-save` branches. That
|
|
makes the scenario variation explicit instead of anecdotal. `Alternate USA` keeps only three
|
|
zero-availability names in this table (`Nuclear Power Plant`, `Recycling Plant`, `Uranium
|
|
Mine`), `Southern Pacific` widens the zero set to twelve (`AutoPlant`, `Chemical Plant`,
|
|
`Electric Plant`, `Farm Rubber`, `FarmRice`, `FarmSugar`, `Nuclear Power Plant`, `Plastics
|
|
Factory`, `Recycling Plant`, `Tire Factory`, `Toy Factory`, `Uranium Mine`), and `Spanish
|
|
Mainline` widens it again to forty-two, including `Bauxite Mine`, `Logging Camp`, `Oil Well`,
|
|
`Port00`, and the `Warehouse00..11` run while also flipping `Recycling Plant` back to
|
|
available. The header lanes just ahead of the table vary coherently with those scenario
|
|
branches too: `Alternate USA` carries `header_word_0 = 0x10000000`, `Southern Pacific`
|
|
carries `0x00000000`, and `Spanish Mainline` carries `0xcdcdcdcd`, while the structural
|
|
fields from `header_word_2` onward remain stable in a fuller fixed-record strip:
|
|
`0x332e`, `0x1`, `0x22`, `0x2`, `0x2`, then the observed capacity/count pair (`0x44`, `0x43`
|
|
in the checked save-side probe), followed by `0x0`, `0x1`; the 9-byte footer still decodes as
|
|
`0x32dc`, `0x3714`, `0x00` in all three checked maps. The runtime-side support family is now
|
|
explicit enough to narrow that strip further without overclaiming ownership: the shared indexed
|
|
collection constructor `0x00518570` and growth helper `0x00517f90` really do seed the same
|
|
collection-shape header family at `[this+0x04/+0x08/+0x0c/+0x10/+0x14/+0x18]` before the live
|
|
payload slab, tombstone bitset, and auxiliary link bands are materialized at
|
|
`[this+0x30/+0x34/+0x3c..+0x44]`. So the file-side prefix now reads more like one source-side
|
|
fixed-record table header than a random magic run: the stable `0x1/0x22/0x2/0x2/0x44/0x43`
|
|
lanes align much better with one fixed-record flag plus one record-stride/growth/bound/count
|
|
family than with direct availability payload. The gap is narrower now too: the later named-
|
|
availability runtime save path does use the shared serializer `0x00517d90` on the non-`.smp`
|
|
package branch, but the `.smp` path still writes direct counted fixed-row runs instead. So the
|
|
file table still is not proven to be a byte-for-byte dump of one single runtime
|
|
indexed-collection body with tombstone and auxiliary-band tails across every save family.
|
|
A wider corpus scan over the visible `.gmp`/`.gms` files makes those two anonymous header
|
|
lanes less mysterious too: the parser currently sees only three stable
|
|
`(header_word_0, header_word_1)` pairs across 79 files with this table shape, namely
|
|
`(0x00000000, 0x00000000)`, `(0x10000000, 0x00009000)`, and
|
|
`(0xcdcdcdcd, 0xcdcdcdcd)`. The zero-availability count varies widely underneath the first and
|
|
third pairs (`0..56` under the zero pair, `14..67` under the `0xcdcdcdcd` pair), so those two
|
|
lanes no longer look like counts or direct availability payload; the safest current read is
|
|
that they are coarse scenario-family or source-template framing above the stable fixed-record
|
|
header strip `0x332e/0x1/0x22/0x2/0x2/(capacity)/(count)/0x0/0x1`, with `0xcdcdcdcd` still
|
|
plausibly acting as one reused filler or sentinel lane rather than a meaningful numeric
|
|
threshold. Current exported
|
|
disassembly notes still do not ground one direct loader-side or editor-side consumer of
|
|
`header_word_0` or `header_word_1` themselves, so that family-marker read remains an
|
|
inference from corpus structure rather than a named field assignment. The save-side runtime
|
|
serializers now sharpen that boundary differently, though: the direct `.smp` path still emits
|
|
the named candidate and locomotive availability families as direct counted fixed-row runs, while
|
|
the non-`.smp` package-save prelude does call the shared indexed-collection serializer
|
|
`indexed_collection_serialize_header_and_live_entry_payload_band` `0x00517d90` on those same two
|
|
runtime collections before continuing into the later tagged-save families. So the anonymous
|
|
file-side `header_word_0/1` pair is no longer excluded by the package-save branch alone, but the
|
|
strongest current ownership boundary is still outside the direct `.smp` runtime row payload:
|
|
they behave like outer source-family framing above the stable fixed-record table rather than like
|
|
one proven loader-side field pair consumed inside the live named-availability collections.
|
|
The new loader-side compare command makes the save-copy claim sharper too: for the checked
|
|
pairs `Alternate USA.gmp -> Autosave.gms`, `Southern Pacific.gmp -> p.gms`, and
|
|
`Spanish Mainline.gmp -> g.gms`, the parsed candidate-availability table contents now match
|
|
exactly entry-for-entry, with the only reported differences being the outer container family
|
|
(`map` vs `save`) and source-kind path (`map-fixed-catalog-range` vs the save-side branch).
|
|
The save-side `.smp` writer is explicit now too: inside `world_runtime_serialize_smp_bundle`
|
|
`0x00446240`, the serializer first writes the current count of `[world+0x66b2]`, then one fixed
|
|
`0x22`-byte candidate-name-plus-dword record for each live entry, then the current count of
|
|
`[world+0x66b6]`, then one fixed `0x41`-byte locomotive-name-plus-dword record for each live
|
|
entry. At version `>= 0x3f2` it also writes one direct six-dword save plateau before the later
|
|
manager bands: one dword from `[world+0x0be2]` and then the five successive dwords at
|
|
`[world+0x0be6/+0x0bea/+0x0bee/+0x0bf2/+0x0bf6]`. Later in the same serializer it brackets the
|
|
live event collection with chunk ids
|
|
`0x4e21/0x4e22` and delegates the actual per-event packed-state save to
|
|
`scenario_event_collection_serialize_runtime_records_into_packed_state` `0x00433060`. So the
|
|
save/load bridge is now symmetric on structure as well as on semantics: the named availability
|
|
collections are not derived-only runtime tables; they are serialized directly into `.smp` and
|
|
then rehydrated back into `[world+0x66b2]` and `[world+0x66b6]` before the later candidate and
|
|
locomotive refresh passes run.
|
|
The non-`.smp` package side is explicit now too. The fallback owner
|
|
`map_bundle_open_reference_package_and_serialize_early_world_datasets` `0x00444dd0` is not a
|
|
generic database opener; it is the early package-save prelude that seeds stage/progress globals
|
|
`0x00620e94/0x0062bec8/0x0062becc/0x0062bed0`, opens one `0x30d40` bundle, and, in the editor-map
|
|
package branch, first runs
|
|
`scenario_state_preseed_named_candidate_availability_overrides_from_editor_map_placed_structures`
|
|
`0x00436a70`, which walks qualifying placed structures, resolves their linked candidate/runtime
|
|
owners, and upserts boolean availability overrides from owner names before the later direct
|
|
collection save. It then serializes the first direct save band in fixed order: chunks
|
|
`0x32c8/0x32c9`, the late setup-preview payload block `[world+0x66be]`, the shared
|
|
indexed-collection serializer `0x00517d90` over candidate named-availability collection
|
|
`[world+0x66b2]`, chunk `0x32dc`, the staged `0x108` profile block under `0x3714/0x3715`, the
|
|
same shared serializer over locomotive named-availability collection `[world+0x66b6]` under
|
|
`0x32dd`, then `world_serialize_runtime_grid_and_secondary_raster_tables_into_bundle`
|
|
`0x00449520` for the early world-grid/core-raster band under chunk families `0x2ee2..0x2f44`,
|
|
then
|
|
`aux_candidate_collection_serialize_records_into_bundle_payload` `0x00416a70` for the direct
|
|
`0x0062b2fc` source-or-auxiliary record family, then
|
|
`placed_structure_collection_serialize_local_runtime_records_into_bundle` `0x00413440`, the
|
|
direct indexed-collection header save on the route-link family `0x006ada90` through
|
|
`0x00517d90`, `placed_structure_collection_serialize_dynamic_side_buffers_into_tagged_bundle`
|
|
`0x00481310` on `0x006cec20`, and
|
|
`linked_route_object_collection_serialize_records_into_tagged_bundle` `0x0041d4c0` on
|
|
`0x0062ba84`, and only then the neighboring reference and manager families before the later
|
|
tagged-collection tail under
|
|
`shell_map_file_world_bundle_coordinator` `0x00445de0`. Current evidence still bounds that
|
|
`0x006ada90` lane as header-only persistence, with live endpoint or route-style state regenerated
|
|
later during bring-up instead of emitted through a separate per-record tagged payload owner. The
|
|
package tail is explicit now too:
|
|
after the manager families it writes one direct dword from `[world+0x19]`, a zeroed `0x1f4`-byte
|
|
slab under chunk `0x32cf`, closes the bundle, derives the preview path through `0x00442740`, and
|
|
then conditionally emits the companion-image sidecar through `0x00441f70` when companion-image
|
|
byte `[world+0x66c8]` is set and the companion-payload rewrite sidecar through `0x00442900`
|
|
when companion-payload byte `[world+0x66c9]` is set. The companion-payload pair is tighter now
|
|
too: `0x004427c0` is the `.tmp`-extension rewrite owner that rewrites one whole sidecar file via
|
|
`0x00553000`, while `0x00442900` is the path-plus-stored-offset sibling that rewrites the same
|
|
middle band from the byte offsets already staged in `[record+0x18/+0x1c]`. The producer boundary
|
|
is tighter than the older shorthand too: current local xrefs still do not show standalone
|
|
byte-local writers for `[world+0x66c8]` and `[world+0x66c9]` in the package path, but the two
|
|
bytes are still written by bulk `[world+0x66be]` copy lanes on restore and multiplayer mirror
|
|
through `0x00446d40` and `0x0046cf40`. The ordinary producer is explicit now too: settings
|
|
dwords `[0x006d4024+0x11471e]` and selector-rooted `0x0062bec4` feed payload bytes `+0x0a/+0x0b`
|
|
through `0x00442ba0`, so the package path is reusing those setup-preview payload lanes rather
|
|
than inventing separate byte-local sidecar gates.
|
|
The two outer shell coordinators above those package and runtime branches are explicit now too.
|
|
`shell_map_file_entry_coordinator` `0x00445ac0` is no longer just the generic open path: it
|
|
clears the caller-supplied success dword, increments nested open counter `0x0062be6c`, and then
|
|
either routes a direct seeded stem into `.smp` restore through
|
|
`world_load_saved_runtime_state_bundle` `0x00446d40` when a live runtime world is already active
|
|
or flag bit `0x8` is set, or routes the same direct seeded stem into the heavier world-entry
|
|
branch `0x00443a50` with one trailing flag derived from `(flags>>2)^1`. Its quickload and
|
|
interactive sides are explicit in the same way: bit `0x1` seeds the Quicksave base stem from
|
|
`0x005ca9cc`, appends `.gmp` under editor-map flag `[0x006cec74+0x68]` and otherwise the same
|
|
`.gms/.gmc/.gmx` family used by the interactive chooser, while the non-Quicksave chooser re-enters
|
|
`shell_file_request_dialog_collect_target_path` `0x004dd010` with load modes
|
|
`4=.gmp`, `8=.gms`, `9=.gmc`, and `10=.gmx`. The save-side sibling
|
|
`shell_map_file_world_bundle_coordinator` `0x00445de0` now has the same shape: it seeds save-side
|
|
selector `0x0062bec4` from shell fields `[0x006d4024+0x11472a]` or `[+0x11472e]` according to the
|
|
same early branch that chooses the save-side variant, accepts either an explicit caller stem, a Quicksave stem from `0x005ca9cc`,
|
|
or the localized `Autosave` stem from string id `387`, chooses save modes
|
|
`3=.gmp`, `0=.gms`, `1=.gmc`, `2=.gmx`, or side-owner-only `11=.gmt`, then either appends the
|
|
fixed `.smp` token and re-enters `world_runtime_serialize_smp_bundle` `0x00446240` when a live
|
|
runtime world exists or falls back to the package side through `0x00444dd0`, with the `.gmt`
|
|
side-owner branch packaged instead into `0x006cd8d8+0x8f48` and submitted through
|
|
`multiplayer_preview_dataset_submit_transport_request` `0x00469d30`. Those two selector dwords
|
|
are now bounded as part of the same settings-window-owned sidecar family toggled by
|
|
`shell_settings_window_handle_message_dispatch_and_persist_display_runtime_sidecar_family`
|
|
`0x00464c80`, not as hidden save/load-only fields.
|
|
The paired load-side seam is explicit now too. `aux_candidate_collection_construct_stream_load_records_and_refresh_runtime_followons`
|
|
`0x004196c0` rebuilds the same `0x0062b2fc` family from the tagged import source around
|
|
`0x005c93fc`, re-entering
|
|
`aux_candidate_record_stream_decode_fixed_fields_and_optional_mask_planes` `0x00414490` for
|
|
each decoded source record before the broader
|
|
rebank-or-clone refresh
|
|
`aux_candidate_collection_rebank_or_clone_records_by_availability_pass_and_refresh_owner_links`
|
|
`0x00419230`. That lower decode body is explicit now too: it imports the six fixed `0x1e`-byte
|
|
stem bands, the small scalar tail through `[record+0xcd]`, applies the two exact-stem rewrites
|
|
for that tail word, allocates and fills up to four optional heap planes at
|
|
`[record+0xcf/+0xd3/+0xd7/+0xdb]`, stamps the corresponding presence latches at
|
|
`[record+0x177/+0x17b/+0x17f/+0x183]`, frees any plane whose decode stayed empty, and seeds
|
|
`[record+0x1a3] = 1.0f`. Save-side ownership is explicit on the other end too:
|
|
`aux_candidate_collection_serialize_records_into_bundle_payload` `0x00416a70` builds its
|
|
temporary scored-node queue through callback
|
|
`aux_candidate_record_chain_callback_collect_unique_link_keys_into_save_queue` `0x00416830`,
|
|
which walks each record's linked chain, chooses one dedupe key from the terminal node, and
|
|
pushes only unique keys into the queue at `0x0062ba58` while counting them in `0x0062ba64`. The
|
|
release side is split cleanly as well:
|
|
`aux_candidate_collection_release_templates_queues_and_indexed_storage` `0x00419680` tears that
|
|
family back down through
|
|
`aux_candidate_collection_release_live_entries_scratch_roots_and_helper_bands` `0x00416950`,
|
|
which walks every live entry, re-enters
|
|
`aux_candidate_collection_release_entry_optional_mask_planes_and_erase` `0x004168e0`, clears the
|
|
scratch root `0x0062b300`, drains the temporary scored-node family `0x0062ba58..0x0062ba74`,
|
|
and only then releases the three helper bands at `[this+0x88/+0x8c/+0x90]`. That follow-on pass
|
|
is tighter now too: `0x00419230` requires both live scenario state and the live
|
|
structure-candidate pool, then
|
|
runs two availability-bank passes keyed by candidate bytes `[+0xba]` and `[+0xbb]`. For each of
|
|
the twelve ordinals it picks one current-bank template entry, tries to reuse one prior target by
|
|
ordinal field `[entry+0x187]`, clones the full fixed record plus up to four optional heap
|
|
payload planes `[+0xcf/+0xd3/+0xd7/+0xdb]` when the target differs from the template, then
|
|
republishes the built-in pass label into `[entry+0x22]` and `[entry+0x04]` and rebinds owner id
|
|
`[entry+0x173]` by exact stem match back into the live candidate pool. So the `0x0062b2fc`
|
|
import seam is no longer just stream-load plus teardown: it now has one explicit post-load
|
|
rebank/projection pass between those endpoints, and the restore-side sibling is explicit too.
|
|
`aux_candidate_collection_restore_temp_record_bank_and_queue_keys_from_packed_state` `0x00413f80`
|
|
restores the queued-key table `0x0062ba6c/0x0062ba70`, the temporary record bank at `0x0062b2f8`,
|
|
and the matching count latches `0x0062ba64/0x0062ba68/0x0062ba74` from packed state. When the
|
|
restore flags demand a live reimport immediately afterward, world-entry restore then re-enters
|
|
`aux_candidate_collection_release_live_entries_then_reimport_records_and_refresh_runtime_followons`
|
|
`0x0041a950`, which releases every live entry through vtable slot `+0x08` and tails straight
|
|
back into `0x004196c0`.
|
|
The neighboring tagged region-manager seam is explicit too. Outside the direct `.smp` branch, the
|
|
live region collection at `0x0062bae0` now has a matched tagged save/load pair:
|
|
`world_region_collection_refresh_records_from_tagged_bundle` `0x00421510` and
|
|
`world_region_collection_serialize_records_into_tagged_bundle` `0x004215e0`. Those owners bracket
|
|
the collection with chunk family `0x5209/0x520a/0x520b`, forward collection-side metadata through
|
|
the indexed-collection helpers, and then dispatch each live region record through the region
|
|
vtable slots `+0x40` and `+0x44`. That keeps the region-record persistence seam distinct from the
|
|
separate geographic-label database load path on `0x006ada80`.
|
|
The two adjacent tagged database families are explicit now too. The geographic-label database at
|
|
`0x006ada80` has the matched tagged pair
|
|
`geographic_label_database_refresh_records_from_tagged_bundle` `0x00461580` and
|
|
`geographic_label_database_serialize_records_into_tagged_bundle` `0x00461650`, both bracketing
|
|
chunk family `0x5209/0x520a/0x520b` and dispatching per-record virtual slots `+0x40/+0x44`
|
|
after the indexed-collection header helpers. The neighboring city-database entry collection at
|
|
`0x006cea50` has the same symmetry on its own tag family
|
|
`0x61a9/0x61aa/0x61ab` through
|
|
`city_database_entry_collection_refresh_records_from_tagged_bundle` `0x00474540` and
|
|
`city_database_entry_collection_serialize_records_into_tagged_bundle` `0x00474610`.
|
|
The adjacent territory and support families are explicit now too. The live territory collection at
|
|
`0x006cfc9c` has the matched tagged pair
|
|
`territory_collection_refresh_records_from_tagged_bundle` `0x00487c20` and
|
|
`territory_collection_serialize_records_into_tagged_bundle` `0x00487cc0`, both bracketing tag
|
|
family `0x61a9/0x61aa/0x61ab`; current per-entry slots `0x00487670/0x00487680` are no-op load
|
|
and save callbacks, so that bundle lane currently persists only collection-side metadata and live
|
|
ids, not per-entry payload. The neighboring support family at `0x0062b244` now has the same
|
|
bounded symmetry too:
|
|
`support_collection_refresh_records_from_tagged_bundle` `0x0040b5d0` versus
|
|
`support_collection_serialize_tagged_records_into_bundle` `0x0040b6a0`, both over chunk family
|
|
`0x2af9/0x2afa/0x2afb` with collection-side metadata forwarded through the indexed-collection
|
|
helpers and per-entry virtual slots `+0x40/+0x44`.
|
|
The restore-side symmetry is explicit too: inside `world_load_saved_runtime_state_bundle`
|
|
`0x00446d40`, the loader first clears `[world+0x66b2]`, reads one counted run of fixed
|
|
`0x22`-byte candidate-name-plus-dword records, and inserts only the rows whose copied names
|
|
survive both fixed built-in stem rejects `0x005c8f94/0x005c8e4c` and then resolve back into the
|
|
live candidate pool `0x0062b268` through `0x00412b70`; the rejected rows are discarded instead of
|
|
blindly restoring stale candidate names, and there is no later candidate-side fallback preseed
|
|
if that validated pass stays empty. The same loader then clears and repopulates `[world+0x66b6]`
|
|
from one counted run of fixed `0x41`-byte locomotive-name-plus-dword records without the
|
|
candidate-side reject-or-resolve filter. After that raw locomotive restore it preserves the older
|
|
empty-collection fallback by re-entering
|
|
`scenario_state_upsert_named_locomotive_availability_record_and_refresh_runtime_usage`
|
|
`0x004350b0` only when `[world+0x66b6]` stayed empty. The startup and restore-side preseed
|
|
callers are tighter now too: the common startup lane at `0x00438d6b` and the `.smp` restore
|
|
fallback at `0x004478ea` both resolve one linked era name through `0x00461c80` and then upsert
|
|
it with literal availability bit `1`, matching the later live-pool sweep inside `0x00461eab`.
|
|
The restore-side condition is explicit now too: `0x004478ea` only runs after the direct counted
|
|
`0x41`-byte restore left `[world+0x66b6]` empty, so this is a true empty-collection fallback
|
|
rather than a second unconditional load pass.
|
|
The same `.smp` loader then brackets the
|
|
live event collection at `0x0062be18` with chunk ids `0x4e21/0x4e22` and delegates the per-event
|
|
packed-state restore to `scenario_event_collection_refresh_runtime_records_from_packed_state`
|
|
`0x00433130`, which itself opens `0x4e99`, refreshes collection-side metadata, opens `0x4e9a`,
|
|
materializes each live event through `0x0042db20`, and closes `0x4e9b`.
|
|
The earlier restore spine is explicit now too. `0x00446d40` dismisses the current shell detail
|
|
controller, tears down the prior runtime world through `world_runtime_release_global_services`
|
|
`0x00434300`, rebuilds the startup-side runtime roots through
|
|
`shell_active_mode_run_profile_startup_and_load_dispatch` `0x00438890`, allocates the new world
|
|
root at `0x0062c120` through `0x0044cf70` using `(width+1, height+1)` from the bundle, and then
|
|
restores one dword per world-grid cell through
|
|
`world_write_companion_float_grid_cell_and_optionally_refresh_rect` `0x0044dca0` before the later
|
|
raster compatibility loops begin. The secondary-raster side is tighter in the same way: for
|
|
versioned bundles at `>= 0x3ec` it restores the four sidecar byte planes through
|
|
`world_load_four_sidecar_byte_planes_from_runtime_bundle` `0x00448f60`, then restores the versioned
|
|
per-cell compatibility bits through the byte-level helpers
|
|
`0x00448c20/0x00448cb0/0x00448d90/0x00448e60/0x00448e90/0x0044de30`, with the older pre-`0x400`
|
|
branch explicitly clearing those newer bits back to the legacy fallback pattern.
|
|
One adjacent mid-restore preview branch is explicit now too: for version `>= 0x3ee` the loader
|
|
restores one width/height-tagged dword surface, optionally resamples it through
|
|
`shell_world_presentation_stage_overlay_rect_from_normalized_bounds` `0x00534930`, republishes it
|
|
through `0x00534730/0x00534af0`, frees the temporary buffer, and then re-enters `0x004882e0` on
|
|
the neighboring manager family.
|
|
The region-side restore band is explicit now too. After seeding default regions through
|
|
`world_region_collection_seed_default_regions` `0x00421b60`, `0x00446d40` restores one counted run
|
|
of fixed `0x29`-byte region rows, resolves or allocates each region through
|
|
`0x00421660/0x00518140`, writes one direct saved dword into `[region+0x272]`, writes one shared
|
|
density dword into both `[region+0x25a/+0x25e]`, and on pre-`0x3f3` bundles synthesizes that
|
|
shared density dword from the legacy lookup table at `0x005f3a28` keyed by the serialized bucket
|
|
field instead of reading it directly, then reruns
|
|
`world_region_refresh_profile_availability_display_strings_for_cached_selector_0x2f2`
|
|
`0x004204c0`, and then reloads the per-region profile
|
|
subcollection at `[region+0x37f]`. It then restores one second counted run of fixed `0x1e+4`
|
|
rows whose copied names must survive the fixed reject stems and still resolve back into the live
|
|
candidate pool before the row is accepted into that region-owned subcollection. That keeps the
|
|
`.smp` restore seam broader and cleaner than before: it is not only named availability and event
|
|
state, but also full region-owned profile and policy rows, one versioned preview surface branch,
|
|
and the older direct companion-float grid restore above them. The pre-recipe save-only scalar
|
|
plateau is explicit on the restore side now too: at version `>= 0x3f2`, `0x00446d40` first reads
|
|
one dword into `[world+0x0be2]`, immediately mirrors that same value into `[world+0x0bde]`, and
|
|
then reads the five successive dwords at `[world+0x0be6/+0x0bea/+0x0bee/+0x0bf2/+0x0bf6]`. So the
|
|
current boundary is tighter than the earlier `save-only plateau` wording: one six-dword save
|
|
band is directly persisted first, and only after that does the separate later
|
|
`0x0fa7..0x0fe7` family-shaped slab lead into the fixed recipe-book root at `0x0fe7`. The
|
|
loader-side bridge explicitly fans the first persisted tuning lane back into the neighboring
|
|
manager scalar at `[world+0x0bde]` before the later tagged database and rule-band restores run.
|
|
The adjacent candidate-side recipe rebuild is structurally closed now too: the local binary now
|
|
only treats the imported supply-marker token family as opaque preserved scenario payload before
|
|
those bands are projected back into live cargo ids through exact-name matching. That same
|
|
selected-year bridge also has the
|
|
explicit companion `world_refresh_selected_year_bucket_scalar_band` `0x00433bd0`, which now
|
|
reads as the real selected-year bucket rebuild owner rather than a generic follow-on math body:
|
|
it bins packed year word `[world+0x0d]` against the 21-step threshold ladder at `0x005f3980`,
|
|
chooses either the first bucket baseline, the terminal bucket scalar at `0x005f3a24`, or one
|
|
interpolated scalar from the paired `(year,value)` table at `0x005f3978/0x005f3980`, and then
|
|
rebuilds the dependent selected-year float band rooted at `[world+0x65/+0x69/+0x6d]` before the
|
|
later threshold and presentation helpers continue; and then
|
|
rehydrates the named locomotive availability collection at `[world+0x66b6]` through
|
|
`locomotive_collection_refresh_runtime_availability_overrides_and_usage_state` `0x00461e00`.
|
|
That locomotive-side restore is tighter now too: its tail explicitly re-enters
|
|
`scenario_state_refresh_cached_available_locomotive_rating` `0x00436af0`, which rebuilds one
|
|
cached available-locomotive rating at `[state+0x4cbe]` from the current year plus the strongest
|
|
surviving available locomotive-side rating scalar `[loco+0x20]`, and the tiny query sibling
|
|
`0x00434080` is now bounded as the shell-side clamped read helper over that same cached field,
|
|
with the grounded shell-side reader later bucketing that value against `40/50/70/85/100`. The
|
|
load-side bridge into `[world+0x66b6]` is tighter too: the constructor-side world-entry bring-up
|
|
sweep over the live locomotive pool `0x006ada84` is the pure preseed path, walking every live
|
|
locomotive, resolving its linked era name through `0x00461c80`, and upserting that name into
|
|
`[world+0x66b6]` through `0x004350b0`. The direct `.smp` restore-side branch inside
|
|
`world_load_saved_runtime_state_bundle` `0x00446d40` first clears the collection, reads one
|
|
counted run of fixed `0x41`-byte locomotive-name-plus-dword records from the bundle, inserts
|
|
them directly through collection vtable slot `+0x04`, and only when that restored collection
|
|
stays empty does it fall back to the same full live-locomotive preseed sweep. The
|
|
neighboring named-candidate bridge is now aligned with that same save/load pattern too: the
|
|
scenario-side named candidate-availability table at `[world+0x66b2]` is another counted fixed
|
|
record run, the `.smp` restore path only keeps rows whose names still resolve into the live
|
|
candidate pool, and the later post-load preseed `0x00437737` plus
|
|
`scenario_state_upsert_named_candidate_availability_record_and_refresh_runtime_filters`
|
|
`0x00434f20` mirror that filtered table back into `[candidate+0x7ac]` across the live candidate
|
|
pool. The
|
|
separate era-side runtime collection is tighter now too: global `0x0062ba88` is constructed in
|
|
the same world-load strip through
|
|
`locomotive_era_collection_construct_and_stream_load_tagged_records` `0x0041e170`, which tails
|
|
into
|
|
`locomotive_era_collection_stream_load_tagged_records_import_engine_type_content_and_seed_runtime_sidecars`
|
|
`0x0041d7c0`. That import seam is tighter now too: collection vtable slot `+0x04` dispatches
|
|
into
|
|
`locomotive_era_collection_allocate_entry_import_tagged_record_and_seed_named_sidecar_handles`
|
|
`0x0041de60`, which loads one `Data/EngineTypes/%1.cgo` payload, seeds the nested collection at
|
|
`[entry+0x196]`, and resolves imported named rows against `[0x006d4020+0x429b8]`; collection
|
|
vtable slot `+0x08` later releases that same live record through
|
|
`locomotive_era_collection_remove_entry_by_id_release_nested_sidecars_and_erase` `0x0041ddc0`.
|
|
The immediate post-load sidecar layer is explicit now too:
|
|
`locomotive_era_collection_publish_intro_notice_and_service_current_year_type2_entries`
|
|
`0x0041e010` can publish the one-shot introductory `0xcb/0xcc` pair on the early-year branch,
|
|
then scans the imported era records for current-year matches whose type dword `[entry+0x41]`
|
|
equals `2`, re-enters the company-policy gate `0x0041d550`, and publishes the matching
|
|
locomotive-side notice through `0x004337c0`. The neighboring query helper
|
|
`locomotive_era_collection_find_first_live_entry_matching_type_and_current_year_window`
|
|
`0x0041e100` closes the small search seam above that same imported collection by returning the
|
|
first live entry whose type and `[entry+0x105..+0x109]` year window admit the current scenario
|
|
year.
|
|
Current package-save inspection still finds no mirrored early world-bundle serializer for
|
|
`0x0062ba88`, so the strongest current boundary is that this era family is content-imported
|
|
during world load rather than package-saved beside the neighboring tagged runtime collections.
|
|
`0x00461650` remains grounded instead as the save-side twin of the geographic-label database at
|
|
`0x006ada80`. The live era records themselves are still later queried through `[loco+0x72]` by
|
|
`0x00461c80/0x00461ca0`.
|
|
The two adjacent live runtime roots in that same world-load strip are tighter now too. Global
|
|
`0x0062ba8c` is constructed through
|
|
`structure_candidate_collection_construct_and_stream_load_records_then_refresh_counts`
|
|
`0x0041f4e0`, which tails into the broader tagged import owner
|
|
`structure_candidate_collection_stream_load_records_seed_name_catalogs_and_refresh_filter_sidebands`
|
|
`0x0041ede0` and then reruns the aggregate counter refresh `0x0041e970`; the same family also has
|
|
the in-place reset sibling
|
|
`structure_candidate_collection_release_live_entries_reimport_tagged_records_and_refresh_counts`
|
|
`0x0041f530`, which releases each live entry through vtable slot `+0x08`, clears the three
|
|
built-in named-candidate slots `[candidates+0x88/+0x8a/+0x8c]`, and rebuilds the same imported
|
|
record set plus summary counts. Global `0x006ada84` is constructed one step later through
|
|
`locomotive_collection_construct_and_stream_load_records` `0x00462520`, which tails into
|
|
`locomotive_collection_stream_load_records_link_era_labels_and_refresh_runtime_availability`
|
|
`0x00461f10`; that load owner resolves linked era records from `0x0062ba88`, folds `[era+0xfd]`
|
|
into imported scalar lanes, builds the paired locomotive text rows through string ids `0x1b3`
|
|
and `0x1b4`, stores the live id into `[loco+0x4f]`, and then re-enters
|
|
`locomotive_collection_refresh_runtime_availability_overrides_and_usage_state` `0x00461e00`.
|
|
Current package-save inspection still finds no mirrored early world-bundle serializer for
|
|
`0x006ada84`; the neighboring package path persists only the named locomotive-availability mirror
|
|
at `[world+0x66b6]`, so the strongest current boundary is another load-side content family rather
|
|
than a bundle-saved live runtime collection.
|
|
The same world-load strip now has the adjacent typed roots grounded too: `0x0062be10` is built
|
|
by `company_collection_construct` `0x00429950`, `0x006ceb9c` by
|
|
`profile_collection_construct` `0x00477740`, `0x006cfcbc` by `train_collection_construct`
|
|
`0x004b2340`, `0x006acd34` by
|
|
`runtime_object_collection_construct_vtable_5cae10` `0x00455320`, and `0x0062b244` by
|
|
`support_collection_construct_seed_counters_and_clear_large_sideband` `0x0040aeb0`. That support
|
|
seam is broader than just tagged save/load now too: the constructor seeds the `0x20`-row
|
|
sideband at `[collection+0x90]`, the package path brackets the live collection under
|
|
`0x2af9/0x2afa/0x2afb`, and the same family now has its live goose-side owners grounded too:
|
|
`support_collection_try_spawn_goose_entry_in_primary_counter_lane` `0x0040b0b0`,
|
|
`support_collection_select_or_spawn_goose_entry_id` `0x0040b2d0`, and the release companion
|
|
`support_collection_release_entry_and_decrement_world_type_counters` `0x0040af00`. That closes
|
|
the local late-state bridge from the saved world slab into live support counters and selection
|
|
state instead of leaving `0x4c9a/+0x4c9e/+0x4cb6` as anonymous neighboring fields. The live
|
|
world root itself is now bounded one layer higher too: `0x0062c120` is published by
|
|
`world_runtime_construct_root_and_seed_global_0x62c120` `0x0044cf70`, and its typed release
|
|
sibling on the old-world teardown path is `world_runtime_release_root_payloads_and_collection_storage`
|
|
`0x00449500`. The profile-side load/save header symmetry is explicit in the same band: runtime
|
|
load refreshes `0x006ceb9c` through
|
|
`profile_collection_refresh_tagged_header_counts_from_bundle` `0x00477780`, while package save
|
|
mirrors those same `0x5209/0x520a/0x520b` header lanes through
|
|
`profile_collection_serialize_tagged_header_counts_into_bundle` `0x004777e0`. The same family's
|
|
active-chairman helper strip is explicit now too:
|
|
`profile_collection_count_active_chairman_records` `0x00477820`,
|
|
`profile_collection_get_nth_active_chairman_record` `0x00477860`, and the id-returning
|
|
companion `0x004778c0`. The live company
|
|
and train collections now have the same bounded symmetry: world-load refresh re-enters
|
|
`company_collection_load_tagged_header_counts_and_refresh_live_records_from_bundle` `0x00429af0`,
|
|
while package save mirrors the same `0x61a9/0x61aa/0x61ab` bracket through
|
|
`company_collection_serialize_tagged_header_counts_and_save_live_records_into_bundle`
|
|
`0x00429b90`; the load-side per-company follow-on is
|
|
`company_refresh_post_load_year_clamp_and_runtime_support_fields` `0x004268e0`, while the
|
|
current save-side per-company callback remains the no-op stub `0x00424000`. The live train
|
|
collection has the same bounded symmetry too: world-load refresh re-enters
|
|
`train_collection_load_tagged_header_counts_and_refresh_live_records_from_bundle` `0x004b2700`,
|
|
while package save mirrors the same `0x5209/0x520a/0x520b` bracket plus the per-train record walk
|
|
through `train_collection_serialize_tagged_header_counts_and_save_live_records_into_bundle`
|
|
`0x004b27a0`. The per-train tagged payload seam is explicit now as well: load-side route-list
|
|
refresh goes through `train_refresh_tagged_route_list_payload_from_bundle` `0x004a84b0`, while
|
|
save-side route-list emission goes through `train_serialize_tagged_route_list_payload_into_bundle`
|
|
`0x004a7030`. The adjacent live train collection utility strip is tighter now too: the same
|
|
family owns collection-wide cleanup passes for positive-sign peer-site rows
|
|
`0x004b2820 -> 0x004af610`, negative-sign dword-key rows `0x004b2860 -> 0x004af760`, an
|
|
all-trains clear of runtime dword `[train+0x1a3]` through `0x004b28a0 -> 0x004a7020`, and the
|
|
broader RGB publish pass `0x004b28e0` that turns per-train scalar `0x004a9630` into linked-owner
|
|
triplets through `0x004a8310`. The same RGB forwarder also now has an adjacent boolean-match
|
|
companion: `0x004b29e0` compares train field `[train+0x51]` against one caller-supplied dword,
|
|
maps the resulting `0/1` through `0x0051dfc0`, and republishes the resulting color triplet
|
|
through the same linked-owner chain. The strip is bounded on both sides now too: `0x004b2a50`
|
|
is the all-zero RGB clear sweep through the same forwarder, while the later collection refresh
|
|
hooks reached from `0x00433b80` are `0x004b2a90` for the shell-gated no-op placeholder pass and
|
|
`0x004b2ae0` for the flagged-train `0x004a8220(1,1)` service sweep.
|
|
The
|
|
same rehydrate band also refreshes the live structure-candidate filter and year-visible counts
|
|
through `structure_candidate_collection_refresh_filter_and_year_visible_counts` `0x0041e970`,
|
|
rebuilding the paired per-slot bands at `[candidates+0x246]` and `[candidates+0x16e]` and the
|
|
aggregate counts at `[candidates+0x31a]` and `[candidates+0x242]`; the same late checkpoint also
|
|
re-enters `placed_structure_collection_seed_candidate_subtype2_runtime_latch` `0x00434d40`,
|
|
which seeds runtime dword `[candidate+0x7b0]` across subtype-`2` candidate records before the
|
|
later world-wide reactivation sweep. That checkpoint also now has an explicit shell-facing scalar
|
|
publisher: `world_publish_shell_controller_progress_scalar_from_year_thresholds_or_selector_overrides`
|
|
`0x004354a0` writes one clamped `0..255` value into the current shell presentation object,
|
|
sourcing it either from the shell selector override pairs or from the scenario-side year-threshold
|
|
band rooted at `[state+0x3a/+0x51/+0x55/+0x59/+0x5d/+0x61]`; and just ahead of the later
|
|
scenario-side recipe rebuild, the same band also re-enters
|
|
`scenario_state_ensure_derived_year_threshold_band` `0x00435603`, which only falls into its
|
|
heavier rebuild body while `[state+0x3a] < 2` and otherwise leaves the derived year-threshold
|
|
companion slots `[state+0x51/+0x55/+0x59/+0x5d/+0x61]` unchanged. That heavier body is tighter
|
|
now too: `scenario_state_rebuild_derived_year_threshold_band` `0x004351c0` samples the current
|
|
shell presentation scalar `[controller->presenter+0x15]`, chooses one of three range profiles,
|
|
seeds floor lane `[state+0x61]` to `0xff`, `0xc8`, or `0xe6`, rebuilds the threshold quartet
|
|
`[state+0x51/+0x55/+0x59/+0x5d]` from the current year plus three shell-side companion integers,
|
|
and, when the caller asks for it or the current shell scalar falls outside the rebuilt band,
|
|
immediately republishes one new clamped `0..255` value back through `0x00523d60`. The neighboring late status
|
|
checkpoints around progress ids `0x196` and `0x197` also share one explicit stage gate now:
|
|
`world_query_global_stage_counter_reached_late_reactivation_threshold` `0x00444dc5` compares the
|
|
global counter `0x00620e94` against threshold `0x9901`, and the two current callers use a
|
|
negative result to clear `[world+0x39]` before the broader world and shell reactivation sweep.
|
|
The later reactivation tail is tighter now too: it includes the region-center world-grid flag
|
|
reseed pass
|
|
`0x0044c4b0`, which clears bit `0x10` across the live grid and then marks one representative
|
|
center cell for each class-`0` region through `0x00455f60`; its immediate sibling `0x0044c450`
|
|
then reruns `placed_structure_rebuild_candidate_cargo_service_bitsets` `0x0042c690` across every
|
|
live grid cell. The small secondary-raster premark helper `0x0044c570` is bounded now too: it
|
|
only admits cells whose current raster byte has no bits in mask `0x3e` and whose parallel class
|
|
query `0x00534e10` is false, then rewrites that masked class field to `0x02` and widens the same
|
|
cached bounds-and-count band `[world+0x21c6..+0x21d6]`. The next helper `0x0044ce60` scans the secondary raster at `[world+0x2135]`
|
|
for cells with any bits in mask `0x3e`, caching min/max bounds plus a marked-cell count in
|
|
`[world+0x21c6..+0x21d6]`; the larger sibling `0x0044c670` then consumes those cached bounds to
|
|
normalize the same raster and rebuild one dependent overlay/cache surface before the later
|
|
route-style rebuild, shell-window, and briefing branches. That overlay side is tighter now too:
|
|
after `0x0044c670` resolves scaled surface dimensions through `0x00534c50`, it walks one local
|
|
`3 x 32` sample lattice through the static offset tables at `0x00624b28/0x00624b48`, keeps only
|
|
secondary-raster classes `4..0x0d`, folds several interpolated `0x0051db80` samples into one
|
|
strongest local score, writes packed overlay pixels into the staged surface buffer, and only then
|
|
publishes that staged overlay through `0x00534af0`. The lower helper layer under that overlay
|
|
pass is tighter now too: `0x00534e10` is the reusable secondary-raster class-set
|
|
predicate for classes `1/3/4/5`, `0x00534e50` is the smaller neighboring class-subset predicate
|
|
for `1/4`, `0x00534ec0` covers `2/4/5`, `0x00534f00` covers `3/5`, `0x00534e90` is the
|
|
marked-bit query over the same 3-byte cell family, and the nearby local counter `0x0044bdb0`
|
|
is now bounded as the 8-neighbor count companion for that same `2/4/5` subset, walking the
|
|
shared `0x00624b28/0x00624b48` offset tables and re-entering `0x00534ec0` on each bounded
|
|
neighbor cell. The first caller cluster around `0x0044bf9d..0x0044c37b` therefore reads as a
|
|
secondary-raster neighborhood service band rather than a generic map scan.
|
|
`0x00533e70` and `0x00534160` are the coarser siblings over the overlay table at `[world+0x1685]`:
|
|
the first clears coarse chunk objects across one clamped rectangle, while the second ensures one
|
|
chunk object and seeds local marks through its deeper stamp helper. One level up, the neighboring
|
|
rect owner `0x005374d0` now reads as the shared secondary-overlay refresh pass: it reruns the
|
|
local sample and unsigned-word reducers `0x00536230/0x00536420`, rebuilds the signed vector byte
|
|
planes through `0x00536710`, and then rebuilds the multiscale support surfaces through
|
|
`0x00533890`, whose inner reducers now explicitly target the packed sample-triplet buffer plus
|
|
the float and unsigned-word support planes rooted at the five-entry per-scale families
|
|
`[world+0x15f1..+0x1601]`, `[world+0x1605..+0x1615]`, and `[world+0x1619..+0x1629]`. The setup
|
|
side of that same family is tighter now too:
|
|
`0x005375c0` is the shared ensure-and-seed owner that allocates the sample, sidecar, mask,
|
|
raster, vector, and coarse-cell tables together; crucially, it seeds `[world+0x1655]` with byte
|
|
`0x02` and `[world+0x1659]` with byte `0x01`, which closes the default-fill split. The local
|
|
component-walk owner under the same neighborhood band is tighter now too: `0x0044c200`
|
|
allocates a temporary `width*height` visit bitmap at `0x0062c128`, seeds one class-`2/4/5`
|
|
starting cell, derives an initial direction index through the remap table `0x005ee5d4`, and then
|
|
fans into the deeper recursive walker `0x0044be20`. That deeper walker widens dirty bounds
|
|
`[world+0x21ad..+0x21b9]`, stamps one companion-word orientation lane through `0x005ee5cc`,
|
|
reuses `0x00534ec0` plus `0x0044bdb0` to filter admissible neighbors, tracks temporary
|
|
visitation in `0x0062c128`, and then applies the local byte-1 edge-bit `0x04/0x08` updates
|
|
before returning. So the `0x0044bf9d..0x0044c422` cluster now reads as a real connected-component
|
|
walk plus edge-flag refresh layer over the secondary raster rather than only a loose group of
|
|
local neighbor counters. The adjacent mutation strip is tighter now too: `0x0044dcf0` refreshes
|
|
companion-word bit `0x200` in one local rectangle by checking whether any neighbor belongs to
|
|
class set `2/4/5`, while `0x0044df10` clears three local sidecar byte planes, demotes class `4`
|
|
to `1` and class `5` to `3`, and then reruns that marked-bit refresh over the surrounding
|
|
`+/-1` window. One level up, `0x0044e500` is the rect-wide owner that recomputes byte-1 edge
|
|
bits `0x04/0x08` for class-`2/4/5` cells, dispatches `0x0044df10` on incompatible local
|
|
patterns, and finally consumes the pending global seed pair at `[0x006d1304+0x78/+0x7c]`
|
|
through `0x0044c200`. The shell-side owner of that pending pair is tighter now too:
|
|
`[0x006d1304]` is the live `PaintTerrain.win` shell singleton while the callback-heavy side also
|
|
keeps a second rooted pointer at `0x006d1334`; the tool constructor snapshots the broader
|
|
terrain-paint state into both families while the world-side raster owner still only consumes
|
|
`[0x006d1304+0x78/+0x7c]` as one pending component-seed pair. Its radial sibling `0x0044e7d0`
|
|
is narrower:
|
|
after validating world-space
|
|
coordinates through `0x00414bd0`, it stamps class-`2` marks into the secondary raster by walking
|
|
one clamped bounding box and admitting cells only when the radial falloff helper `0x0051db80`
|
|
stays positive before re-entering `0x0044c570`. The two small support predicates under that same
|
|
strip are now explicit too: `0x00414bd0` is the float grid-bounds gate, and `0x00449df0` is the
|
|
integer rectangle clamp-and-validity helper shared by the local mutation owners. One level up,
|
|
the broader rect-scoped owner is tighter now too:
|
|
`world_rebuild_secondary_raster_derived_surface_and_companion_planes_in_rect` `0x0044e940`
|
|
first reclamps the caller rectangle through `0x00449df0`, reruns the local edge-refresh owner
|
|
`0x0044e500`, lazily ensures one presentation target through
|
|
`0x0051f090/0x00534910/0x00534920/0x00534930`: the first helper resolves the shared
|
|
world-presentation owner, `0x00534910/0x00534920` expose the current staging flag and buffer
|
|
root, and `0x00534930` captures one normalized-bounds rect into that staging buffer before the
|
|
later publish step `0x00534af0`. The same family then resolves scaled target dimensions through
|
|
`0x00534c50` before allocating one temporary `width*height` mask. Its main scan then
|
|
walks the live secondary raster `[world+0x165d]` through the same class predicates
|
|
`0x00534e10/0x00534e50/0x00534f00/0x00534ec0`: class-`1/3/4/5` cells force `0xff` into the four
|
|
sidecar byte planes `[world+0x1631..+0x163d]`, while the broader per-cell pass writes packed
|
|
values into the ensured target through `0x00534730` and also updates nibble lanes at byte offsets
|
|
`+0x2` and `+0x5` inside the same three-byte secondary-raster cell family. After the publish it
|
|
notifies the shell owner at `0x0062be68`, re-enters
|
|
`world_refresh_all_grid_cell_secondary_raster_derived_bits` `0x00449f80` and `0x004881b0`, frees the
|
|
temporary mask, expands the caller rectangle by dirty bounds `[world+0x21ad..+0x21b9]` through
|
|
`0x00536710`, and finally seeds companion byte `[world+0x162d]` with `0xc4` on cells selected
|
|
from mask plane `[world+0x1655]`. So the `0x0044e500 -> 0x0044e940` band is now a real
|
|
derived-surface and companion-plane rebuild family rather than only a loose collection of local
|
|
raster mutations. The local
|
|
evidence now also supports a stronger negative conclusion: unlike `[world+0x1655]`, that second
|
|
mask plane is not part of the actively rebuilt runtime overlay path, and in the grounded local
|
|
corpus it behaves only as a separately seeded, cleared, and persisted sibling plane. One level
|
|
lower, the
|
|
base-plane allocator `0x00532c80` now reads more cleanly too: it is the narrower owner that
|
|
clears `[world+0x15e1]`, optionally applies the current grid dimensions, allocates the base
|
|
float-summary plane `[world+0x1605]`, the four sidecar byte planes `[world+0x1631..+0x163d]`,
|
|
both one-byte mask planes `[world+0x1655/+0x1659]`, and the packed secondary raster
|
|
`[world+0x165d]`, then seeds those planes with the same `0x02/0x01/0x00` default split. The
|
|
load-side owner for those same planes is tighter now too: the constructor thunk `0x0044e910`
|
|
immediately feeds the heavier payload body `0x0044cfb0`, which reads the rooted chunk families
|
|
`0x2ee2/0x2ee3/0x2ef4/0x2ef5/0x2ef6/0x2ee4/0x2ee5/0x2f43/0x2f44`, allocates the core world-grid
|
|
and secondary-raster arrays `[world+0x2129..+0x2141]` plus the route-entry collection
|
|
`0x006cfca8`, initializes every grid-cell record through
|
|
`world_grid_cell_record_refresh_from_bundle_bitmask_and_optional_6byte_list` `0x0042ae50`, and
|
|
only then hands off
|
|
into `world_compute_transport_and_pricing_grid` `0x0044fb70`, the neighboring presentation
|
|
refresh `world_count_secondary_raster_cells_outside_class_set_1_3_4_5_and_store_0x21a9`
|
|
`0x00449f20`, and the shell-mode pulse `0x00484d70`. So the `0x0044e910 -> 0x0044cfb0`
|
|
load side is now bounded as the heavy world-grid and secondary-raster bundle-load body rather
|
|
than just another anonymous constructor tail. One
|
|
level lower on that same post-load seam, the full-grid derived-bit companion is tighter now too:
|
|
`world_refresh_all_grid_cell_secondary_raster_derived_bits` `0x00449f80` walks the live
|
|
`0x1d7`-byte grid-cell records twice, first re-entering
|
|
`world_grid_cell_refresh_bits_0x01_0x02_from_anchored_4x4_secondary_raster_class_counts`
|
|
`0x0042b050` to refresh bits `0x01/0x02` from each cell's anchored `4x4` secondary-raster
|
|
window rooted at `[cell+0xe7/+0xe9]`, then re-entering
|
|
`world_grid_cell_refresh_bit_0x08_from_neighbor_cell_bit_0x01_clear_offsets` `0x0042bc70`
|
|
to refresh bit `0x08` from the fixed neighbor-offset tables `0x00624b28..0x00624b54`.
|
|
That closes the immediate world-grid restore side of this load/save branch instead of leaving the
|
|
last post-load refresh passes as raw helper calls.
|
|
One
|
|
level higher again, the broader world-presentation reinitializer `0x00537e60` now sits above
|
|
that base allocator and the larger support-family ensure path `0x005375c0`: it stores the live
|
|
grid dimensions, hard-resets the whole overlay runtime family through `0x00532590`,
|
|
and that reset strip is no longer opaque either: the immediately preceding local helpers
|
|
`0x00532310..0x00532550` now bound one compact overlay-local state family under the same owner.
|
|
`0x00532310/0x00532360/0x00532370/0x00532380` own the seven-dword companion block
|
|
`[world+0x15b5..+0x15cd]` together with live flag byte `[world+0x15b4]`; `0x005323f0`,
|
|
`0x00532460`, and `0x00532490` are the ensure, publish, and query strip for cached surface root
|
|
`[world+0x478]` using saved dimensions `[world+0x159c/+0x15a0]`; `0x005324e0/0x00532500` are the
|
|
live-flag setters for `[world+0x159b]`; `0x00532510` is the direct setter for mode byte
|
|
`[world+0x159a]`; and `0x00532520/0x00532550` own the four-dword saved dimension quad
|
|
`[world+0x15a4..+0x15b0]`. So the broader `0x00532590` reset really does sit at the base of a
|
|
concrete local cached-surface and companion-block owner family, not just a pile of unrelated
|
|
presentation fields. The reinitializer then
|
|
reinitializes the secondary-overlay family for those dimensions, and then republishes the
|
|
neighboring overlay constants and support owners used by both the world-side reattach branch and
|
|
the `.smp` restore-side presentation rebuild path, including several owners that all funnel
|
|
through the shared static-template slot allocator `0x00532ad0` over the local `0x100` pointer
|
|
band at `[world+0x08]`. Those neighboring owners are tighter now too: `0x00535070` is the small
|
|
primary overlay-surface-or-template setup owner; `0x00535100` is the heavier requested-dimension
|
|
apply and four-slot overlay-surface rebuild owner used by the setup-side regenerate branch and
|
|
the load-side bundle path; while `0x005356e0` and `0x00535890` seed two
|
|
larger static-template slot bands rooted at `[world+0x1568/+0x156c/+0x1574/+0x1578]` and
|
|
`[world+0x1560/+0x1564]` respectively; the remaining heavier sibling `0x00535430` now reads as a
|
|
shared four-slot overlay-surface rebuild owner that resamples one source or fallback descriptor
|
|
into a short local slot strip above `[world+0x155c]`. The immediate helper strip under that same
|
|
family is tighter now too: `0x00534f60` is the small presentation-owner base init above
|
|
`0x00532590`; `0x00534f80` releases one transient surface handle at `[world+0x478]` and clears
|
|
byte `[world+0x159b]`; `0x00532760` releases the current overlay slot chosen by selector
|
|
`[world+0x1558]`; `0x005327a0` clamps two requested surface dimensions down to supported
|
|
power-of-two sizes while also enforcing shell display caps from `[0x006d4024+0x114243/+0x114247]`;
|
|
`0x00532860` is the local twelve-slot stitching pass over the parallel bands rooted at
|
|
`[world+0x08/+0x0c/+0x18]`, copying terminal rows and edge dwords between those sibling slot
|
|
surfaces before finalizing the primary band through `0x00541c10`;
|
|
`0x00532960` is the adjacent paired projection helper that maps two caller counters through the
|
|
current `16x16` and `4x4` rounded grid quanta and writes the resulting coarse offsets back to two
|
|
out-pointers;
|
|
`0x005329e0` maps one `(x,y)` pair into a `1`-based coarse `4x4` overlay region id using the
|
|
current rounded grid dimensions; `0x00532a30` is the direct getter for local dword `[world+0x1554]`,
|
|
which still reads only as the live count or tag for this overlay slot band;
|
|
`0x00532a40` and `0x00532aa0` are the time-selected query helpers over the first and second
|
|
template-seeded slot bands rooted at `[world+0x1568/+0x156c]` and `[world+0x1560/+0x1564]`; and
|
|
`0x00532a90` is the direct getter for trailing fallback slot `[world+0x1578]`. The next adjacent
|
|
owner is tighter now too: `0x00532b30` is the shared release/reset path for the local overlay
|
|
slot band at `[world+0x08]`, with a split release policy keyed by shell flag
|
|
`[0x006d4024+0x11422e]` and a special forced-direct range for slot ids `1..0x10`, after which it
|
|
clears band fields `[world+0x1554/+0x1568/+0x1570/+0x155c/+0x1560/+0x1564]`. The tail of that
|
|
same reinitializer is tighter one level up too: `0x00527ce0` is the broader ensure owner that
|
|
watches current grid extents plus world tag `[world+0x2121]`, re-enters `0x00532860` when those
|
|
cached values change, rebuilds or releases local helper `[this+0x65]`, and then clears the two
|
|
large global scratch planes rooted at `0x008f2520` and `0x00b33530`. The tail of that same
|
|
reinitializer is
|
|
tighter now too: after the larger support-family setup it seeds one seven-entry default overlay
|
|
companion set through `0x005373b0`, whose inner allocator `0x00535950` populates the local
|
|
`0x1b`-entry slot table from the static template rows `0x005dd300..0x005dd378`. The lifecycle
|
|
side is tighter in the same way now: `0x00536044` is the shared teardown owner that frees those same
|
|
three five-entry support families together with both mask planes, the packed secondary raster,
|
|
the vector-byte planes, the local staging buffer, and the neighboring sidecar or coarse-cell
|
|
tables. The remaining base-float lane is tighter too: the larger rebuild owner
|
|
`0x00538360` now clearly writes one base float-summary field into `[world+0x1605]`, clears both
|
|
one-byte mask planes, and then only repopulates the primary mask plane `[world+0x1655]` for the
|
|
qualifying class-`1` interior cells before re-entering `0x00532d90` to normalize that base
|
|
float-summary plane globally and `0x00532f60` to expand positive cells through one caller radius.
|
|
That asymmetry is now enough to close the local semantic edge: `[world+0x1655]` is the actively
|
|
rebuilt primary overlay mask, while `[world+0x1659]` is only the separately seeded and persisted
|
|
secondary mask sibling with no comparably grounded distinct read-side consumer. The only grounded
|
|
getter call to its root accessor `0x00533b60` is the shell staging branch at `0x00525bad`, and
|
|
that branch immediately discards the returned pointer. The bundle side is now explicit too:
|
|
`.smp` save-load treats the two mask planes as separate payloads with chunk ids `0x2cee` for
|
|
`[world+0x1655]` and `0x2d51` for `[world+0x1659]`, while the neighboring `0x2d49/0x2d50`
|
|
branches are the separate packed secondary-raster import lanes rather than alternate consumers
|
|
of the second mask plane. So, in the mapped local code, `0x1659` is best treated as a persisted
|
|
compatibility or seed-state sibling, not as a second actively consumed runtime overlay mask. The
|
|
transport/pricing preview side is tighter now too: `0x00538060` sits directly beneath
|
|
`0x0044faf0`, first seeds one preview handle through `0x00535430` using the short `C_`
|
|
descriptor, temporarily overrides shell globals
|
|
`[0x006d4024+0x11423b/+0x11423f/+0x114254/+0x114255]`, and then loads `%1.tga` through
|
|
`0x0053c1c0 -> 0x00541970`. It clamps that sampled image into the `0x401 x 0x401` range,
|
|
rewrites `[world+0x1605]` plus the mask/raster family `[world+0x1655/+0x1659/+0x165d]` from the
|
|
sampled pixels, optionally re-enters `0x00532d90/0x00532f60`, republishes the seeded preview
|
|
handle through `0x0053c000`, and then re-enters `0x005375c0(1, 0, 0)`. The small shell-global
|
|
owner it also touches is tighter now too: `0x006d401c` is constructed by `0x00538640`,
|
|
`0x005386e0` publishes the primary timed text lane, `0x005387a0` publishes the secondary fixed
|
|
`10000` ms lane, `0x00538810` finds the first registered shell window containing one child
|
|
control id by walking each window through `0x0053f830`, and `0x00538840/0x00538880/0x00538890`
|
|
manage the owner's local `1000`-slot active-token table keyed by child control id. The adjacent
|
|
list strip is tighter too: `0x00538990` is the registered-window virtual-slot-`0` gate that
|
|
stops on the first zero return, `0x005389c0` is the shared unlink helper for the same doubly
|
|
linked list rooted at `[owner+0x00/+0x04]`, `0x00538a60` is the zero-counter gate over
|
|
`[owner+0xc60]`, `0x00538a70` is the matching full reset-and-release body used during bootstrap
|
|
teardown, and `0x00538a10/0x00538a20/0x00538a30/0x00538a40` are the direct getter, setter,
|
|
increment, and clamped decrement helpers for the owner's scalar lanes `[+0xc5c]` and `[+0xc60]`.
|
|
The next shell-runtime strip is tighter now too: `0x005388d0` is the shared `12`-dword
|
|
descriptor dispatcher with the optional override validator at `[owner+0xc75]` and the recursive
|
|
`kind 6 -> 0xb7` rewrite; `0x00538c70` is the prioritized cached-text owner over
|
|
`[owner+0xbd8/+0xbdc/+0xbe0/+0xbe4]` that emits descriptor kind `0xae` through `0x005388d0`;
|
|
`shell_dispatch_synthetic_12_dword_descriptor_from_five_scalars` `0x00538e00` is the five-scalar
|
|
descriptor-synthesis wrapper above that same dispatcher;
|
|
`0x00538e50` is the sorted registered-window insert owner over node key `[node+0x21]`;
|
|
`0x00538ec0` is the refresh sweep over the indexed helper collection rooted at `[owner+0xc69]`;
|
|
and `0x00538f10` is the broader optional-window publish plus blocking descriptor loop used by
|
|
modal launchers and some shell transition paths.
|