Add hook debug tooling and refine RT3 atlas

This commit is contained in:
Jan Petykiewicz 2026-04-08 16:31:33 -07:00
commit 57bf0666e0
38 changed files with 14437 additions and 873 deletions

View file

@ -103,15 +103,18 @@ transition.
## Map and Scenario Content Load
- Roots: `shell_map_file_entry_coordinator` at `0x00445ac0`, the first grounded world-entry branch
- Roots: `shell_map_file_entry_coordinator` at `0x00445ac0`, the larger active-mode profile owner
`shell_active_mode_run_profile_startup_and_load_dispatch` at `0x00438890`, the shell-mode
switcher `shell_transition_mode` at `0x00482ec0`, the first grounded world-entry branch
`world_entry_transition_and_runtime_bringup` at `0x00443a50`,
`shell_map_file_world_bundle_coordinator` at `0x00445de0`, reference-database setup via
`map_bundle_open_reference_databases` at `0x00444dd0`, and narrower loaders such as
`map_load_geographic_label_database` and `map_load_city_database`.
- Trigger/Cadence: shell tutorial launch, editor or detail-panel file actions through `fileopt.win`,
map-scenario open paths, and scenario-text export batch commands.
- Key Dispatchers: `shell_map_file_entry_coordinator`, `world_entry_transition_and_runtime_bringup`,
`world_runtime_release_global_services`, `shell_map_file_world_bundle_coordinator`,
- Key Dispatchers: `shell_map_file_entry_coordinator`,
`shell_active_mode_run_profile_startup_and_load_dispatch`, `shell_transition_mode`,
`world_entry_transition_and_runtime_bringup`, `world_runtime_release_global_services`, `shell_map_file_world_bundle_coordinator`,
`map_bundle_open_reference_databases`, `map_load_geographic_label_database`,
`map_load_city_database`, `scenario_text_export_build_language_file`,
`scenario_text_export_report_language_file`, `scenario_text_export_batch_process_maps`.
@ -137,7 +140,188 @@ transition.
mode `11` is tighter now too: it still maps to `.gmt`, but instead of looking like another
gameplay save family it conditionally diverts into the same `.gmt` preview-surface pipeline owned
by the Multiplayer preview dataset object at `0x006cd8d8`, and only falls back to the normal
reference-bundle path when that dataset object is absent.
reference-bundle path when that dataset object is absent. The shell-side mode owner above those
file coordinators is clearer now too. `shell_transition_mode` no longer reads like a generic mode
switch: its constructor jump table now resolves mode `1` to `Game.win`, mode `2` to `Setup.win`,
mode `3` to `Video.win`, mode `4` to `LoadScreen.win`, mode `5` to `Multiplayer.win`, mode `6`
to `Credits.win`, and mode `7` to `Campaign.win`. The strongest current load-side owner inside
that table remains the mode-`4` branch around `0x4830ca`, which publishes the new active mode
object into `0x006cec78` and then calls `shell_active_mode_run_profile_startup_and_load_dispatch`
as `thiscall(active_mode, 1, 0)`. The caller split above that owner is tighter now too:
`world_entry_transition_and_runtime_bringup` reaches the same owner at `0x443b57` with `(0, 0)`
after dismissing the current shell detail panel and servicing `0x4834e0(0, 0)`, while the
saved-runtime path at `0x446d7f` does the same before immediately building the `.smp` bundle
payloads through `0x530c80/0x531150/0x531360`. That makes the `LoadScreen.win` startup lane the
only currently grounded caller that enters `0x438890` with `(1, 0)` instead of `(0, 0)`. The
internal selector split in `0x438890` is tighter now too: `[0x006cec7c+0x01]` is a separate
seven-way startup selector, not the shell mode id. Values `1` and `7` load `Tutorial_2.gmp` and
`Tutorial_1.gmp`, values `3/5/6` collapse into the same profile-seeded file-load lane through
`0x445ac0([0x006cec7c]+0x11, 4, &out_success)`, value `2` is a world-root initialization lane
that allocates `0x0062c120` and then forces selector `3`, and value `4` is the setup-side world
reset or regeneration lane that rebuilds `0x0062c120` from `0x006d14cc/0x006d14d0` before later
world setup continues. The write side is tighter now too: `Campaign.win` writes selector `6`,
`Multiplayer.win` writes selector `3` on one pending-status path, and the larger `Setup.win`
dispatcher writes selectors `2`, `3`, `4`, and `5` on its validated launch branches. That makes
the file-load subfamily read less like one generic save-open branch and more like a shared
profile-file lane reused by setup, multiplayer, and campaign owners. The world-entry owner
boundary is tighter now too: `world_entry_transition_and_runtime_bringup` at `0x00443a50` no
longer stops at the initial shell transition and world allocation head. The same grounded
function continues through the larger post-load generation tail up to `0x00444dc2`, which means
the later `Setting up Players and Companies...` and neighboring post-load passes are not
floating raw callsites after all. That same owner now clearly covers the event-runtime refresh
through `0x433130`, chairman-profile materialization through `0x437220`, neighboring route and
tracker refresh families, and the one-shot kind-`8` runtime-effect service through `0x432f40`
before clearing shell-profile latch `[0x006cec7c+0x97]`. The `Setup.win` dispatcher
is less opaque now too: the early `0x0bc1..0x0c24` family is mostly fixed submode selection above
`0x00502c00`, except for the separate `0x0bc2/0x0bc5/0x0bc6/0x0bc7` shell-open quartet above
`0x00501f20`; `0x0c1f` is the settings-window escape; `0x0c1e/0x0c20/0x0c22` are direct shell
requests into `0x00482150`; the fixed submode buttons now have concrete lower targets such as
`0x0bc1/0x0bc8 -> 15`, `0x0bc3 -> 16`, `0x0bc4 -> 1`, `0x0c80 -> 13`, `0x0c1c -> 17`,
`0x0c1d -> 2`, `0x0c24 -> 14`, `0x0c81 -> 14`, `0x0c82 -> 6`, `0x0c83 -> 10`, and
`0x0c84 -> 12`; the
`0x0ce6/0x0ce7/0x0d49/0x0d4a/0x0e82/0x0e83` branches are bounded list or slider adjustments on
staged setup fields; and the later `0x0dca/0x0dcb/0x0de9/0x0df3/0x0e81/0x0f6f/0x0f70` controls
are the explicit selector-writing launch buttons rather than one anonymous validated-launch blob.
The constructor-side callbacks are tighter too: control `0x0ce8` is a table-driven payload-label
draw callback above `0x00502030`, not another launch root, and controls `0x0e86` and `0x0e87`
do not select more setup roots; they update the persisted shell-state selector pairs at
`[0x006cec74+0x233/+0x237]` and `[0x006cec74+0x23b/+0x23f]` through `0x00502160` and
`0x005021c0`, then immediately save config through `0x00484910(1)`. The constructor body is
tighter too: it seeds the initial `Setup.win` state by running `0x502910`, `0x502550`, and
`0x502c00(1)` before the user interacts with the window, installs `0x0c80..0x0c86` and
`0x0f6f..0x0f71` as homogeneous button bands, and treats `0x0e88` as one separate special
control with retuned float fields rather than another ordinary launch root. The remaining
optional constructor child `0x0bd0` is tighter now too: it is built from a separate template
block and optional owned heap object before registration, not another hidden setup-root button.
The generic shell helper layer beneath that constructor is tighter now too: `0x53fa50` is the
shared resource-bind and child-list initialization helper, `0x53f830` is the child-control
lookup-by-id helper over the intrusive list at `[this+0x70]`, `0x558130` is the child-control
finalizer that stamps the owner pointer and resolves localized captions before the control goes
live, and `0x53f9c0` is the ordered child-control registration helper used by the optional
`0x0bd0` branch and other shell dialogs.
The submode selector itself is tighter now too because its button-state lane is mostly decoded:
`0xbc5` tracks submode `15`, `0xbc6` tracks `16`, `0xbba` tracks `2`, `0xbbb` tracks `3`,
`0xbc3` tracks `13`, `0xbbc` groups `3/4/5`, `0xbbd` tracks `4`, `0xbbe` tracks `5`, `0xbbf`
groups `6/12/14`, `0xbc0` tracks `7`, `0xbc1` tracks `8`, `0xbc2` tracks `9`, `0xe75` tracks
`10`, and `0xf6e` tracks `17`. RT3.lng and the setup art families now also make several of those
top-level roots read less like anonymous ids and more like real menu panels: submode `1` is the
strongest current landing-panel fit, `2` is the `Single Player` root, `7/8/9` are the
`Editor` / `New Map` / `Load Map` family, `15` is `Extras`, and `17` is `Tutorial`. By
elimination against the separate shell `Credits.win` mode, the remaining top-level `Setup.win`
roots now most safely read as `13 = Multi Player` and `16 = High Scores`.
The file-backed side is tighter too: `0x502c00` now maps submodes exactly as `4 -> dataset 5`,
`9 -> 4`, `6 -> 8`, `10 -> 6`, `12 -> 10`, and `14 -> 9`, so the saved-game-backed family is
no longer one blurred list pane but a small set of stable dataset variants above
`0x4333f0/0x4336a0`.
The file-backed header split is tighter too: `0x5027b0` now maps the top header-control ids as
`4 -> 0xd4b`, `9 -> 0xde8`, `6/12/14 -> 0xdf2`, and `10 -> 0xe85`. RT3.lng closes one earlier
mistake here: those values are local setup control or resource ids, not localized text ids.
The setup art bundle now tightens that family split one step further too: under `rt3_2WIN.PK4`
the distinct file-backed setup art families are the shared `Setup_Load` lane and the separate
`Setup_Sandbox` lane, which matches the selector-side evidence that mode `10` is the
sandbox-backed `new` list while mode `12` is its `load` sibling. Combined with the builder at
`0x4333f0`, that shows only submodes `4` and `10` using the alternate localized-stem list-label
path; `6`, `9`, `12`, and `14` keep the direct filename-normalization lane.
The grouped `3/4/5` family is narrower now too: `0x0ce5` is no longer part of it, because that
control writes selector `3` and then selects submode `9` as the `Load Map` sibling. The nearby
`0x0dcb` branch instead conditionally selects submode `5` or `3`, which keeps `3` as the
strongest current `New Game` / `Options` companion and `5` as the strongest current `Sandbox`
companion. The file-backed single-player side is tighter in the same way now: modes `4` and `10`
are the only siblings using the alternate localized-stem row-label path, so they now read most
safely as the two setup-local template or profile list variants rather than ordinary save lists.
Mode `10` is the stronger one of the pair because neighboring validated launch control `0x0e81`
both routes into selector `5` and sets sandbox byte `[0x006cec7c+0x82] = 1`, which makes it the
strongest current fit for the setup-local `New Sandbox` list. The distinct `Setup_Sandbox` art
family in `rt3_2WIN.PK4` now reinforces that same split one step further, which makes mode `12`
the strongest closed fit for the paired `Load Sandbox` lane; mode `4` is therefore the strongest
remaining non-sandbox peer in that same pair and now most safely reads as the setup-local `New
Scenario`-style chooser. Modes `6`, `12`, and `14` now tighten one step further as the three
selector-`3` direct-filename setup-local `load` siblings because they stay on the direct
filename-normalization lane, share the same `0xdf2` header family, and clear the same
presence-style latch `[0x006cec7c+0x97]`; mode `14` is the strongest current landing panel for
that cluster because `0x0c24` jumps to it directly while `0x0c82` and `0x0c84` only reach the
sibling modes `6` and `12` from inside the same load family. Current control-pairing and
setup-art evidence now make `12 = Load Sandbox` the strongest closed per-submode assignment. The
remaining non-sandbox pair is closed now too: the deeper bundle filter at `0x433260`
distinguishes dataset `9` from dataset `8` by one extra nonzero payload-flag family, and the
editor-side metadata path now grounds `[0x006cec78+0x66de]` as the direct `Campaign Scenario`
checkbox bit because `editorDetail.win` ties control `0x5b6e` to localized ids `3160/3161`.
That makes dataset `9` the campaign-designated load family and dataset `8` the ordinary scenario
load family, so `14 = Load Campaign` and `6 = Load Scenario` now read as grounded rather than
residual. `0x502910` is
tighter in a
corrective way too: it is not a mode-`3`-only helper after all, but the shared non-file-backed
payload panel that formats
`0xcf3/0xcf4/0xcf5/0xd4f`, mirrors option byte `[0x006cec7c+0x7d]` into `0x0ce9..0x0ced`,
rebuilds row host `0x0ce8` from payload bytes `[+0x31b/+0x31c]`, and mirrors live row markers
into `[0x006cec7c+0x87]`. That makes mode `3` just one user of the shared payload-driven panel,
not the sole owner of it.
The payload-helper cluster under that panel is tighter now too: `0x502220` does not just
republish labels and the preview surface. It first re-enters
`shell_setup_load_selected_profile_bundle_into_payload_record` `0x442400`, which clears one full
`0x100f2`-byte setup payload record, builds a rooted path from the staged profile stem, opens the
selected bundle through `0x530c80`, and then reads either the ordinary saved-profile chunk family
or the map-style chunk family through `0x531150/0x531360` depending on the selected extension
shape. Only after that does `0x502220` copy payload fields `+0x14/+0x3b2/+0x3ba/+0x20` into the
staged runtime profile through `0x47be50`, which in turn normalizes the payload category bytes at
`[payload+0x31a + row*9]` and the local marker-slot bytes at `[payload+0x2c9..]` through
`0x47bc80`. The adjacent region-side worker family is tighter in a negative way too: the setup
payload loader is now clearly separate from the broader region-building and placement cluster
around `0x422320..0x423d30`, whose current grounded helpers now include `0x422320`, `0x4228b0`,
`0x422900`, `0x422a70`, `0x422be0`, `0x422ee0`, `0x4234e0`, `0x4235c0`, and
`world_region_refresh_cached_category_totals_and_weight_slots` `0x423d30` rather than one hidden
setup-only panel. The leading region helper is no longer unnamed either: `0x422320` is now
bounded as the recurring cached-structure-scalar normalization pass that writes
`[region+0x2e2/+0x2e6/+0x2ea/+0x2ee]`, while `0x422a70` is the shared placement-validation and
commit gate beneath both the per-region worker and one second world-side placement loop. The
neighboring `0x4234e0` accessor is tighter too: it is the shared projected structure-count scalar
query by category that later feeds both the per-region placement family and the map-editor city
count stats report. So the remaining gap is no longer “what are these setup payload helpers
doing,” but only how aggressive we want to be when naming the last top-level setup roots from
mostly RT3.lng and asset-side evidence.
The adjacent summary helper is tighter too: `0x502550` is not another hidden submode owner. It
republishes the staged path tail in `0xe7f`, the scalar summary in `0xe84`, the two persisted
selector lists in `0xe86/0xe87`, and the config toggles in `0xe88/0xe89/0xe8a`.
The remaining top-level gap is cleaner now too: submode `16` still has no distinct downstream
helper or launch branch in the local selector/refresh family, but it is no longer a blank bucket.
Current evidence now bounds it as the `0x0bc3 -> 16` top-level button whose visual-state lane is
surfaced through control `0xbc6`, and the strongest residual fit is `High Scores` because
`Credits` already lives in separate shell mode `6`.
The validated launch lane is tighter now too: it no longer just writes selector `3` or `5` as
one undifferentiated blob, and it no longer includes `0x0ce5` or `0x0dcb`. `0x0ce5` is the
`Load Map` selector because it writes selector `3` and then selects submode `9`, while `0x0dcb`
is the later conditional `5/3` companion-selector sibling rather than a file launch. The actual
validated staged-profile lane is now bounded more narrowly: `0x0cf6` and `0x0e81` are the
selector-`5` siblings, while the neighboring selector-`3` validated lane is at least shared by
`0x0de9` and `0x0df3`; the shared bridge at `0x4425d0` then forces `[0x006cec7c+0xc5] = 1`,
mirrors payload bytes into `[profile+0xc4]`, `[profile+0x7d]`, and `[profile+0xc6..+0xd5]`, and
only then issues shell request `0x0cc`. Only `0x0e81` also sets `[0x006cec7c+0x82] = 1`, which
is currently the strongest sandbox-side anchor beneath the later `.gmx` load family.
That launch band is slightly tighter now too: `0x0dca` is the grayscale-map picker branch above
the `TGA Files (*.tga)` / `.\Data\GrayscaleMaps` helper at `0x004eb0b0`, not another ordinary
save-file validator. That launch band is tighter in a second way too: `0x0ddf` is not a lobby
branch after all, but the separate windowed-mode-gated grayscale-heightmap generation path. It
reopens the `TGA Files (*.tga)` / `.\Data\GrayscaleMaps` picker through `0x0042a970`, validates
the chosen image through `0x005411c0`, and only then writes startup selector `2`. The fixed-
button side is tighter too: submode `15` now aligns with the `Extras` family because it sits
above the Readme/Weblinks shell-open quartet and the return-to-extras sibling, while submode
`17` now aligns with the tutorial chooser because it is the only branch that later exposes
startup selectors `1` and `7`, which RT3 uses for `Tutorial_2.gmp` and `Tutorial_1.gmp`. The
map-root family is tighter too: submodes `7/8/9` are the only setup branch that flips the file
root into
`maps\\*.gm*`, with mode `8` specifically the grayscale-heightmap picker and mode `9` the
file-backed map-list sibling.
Submode `13` is slightly tighter now too: current local evidence shows that it stays outside
both the dedicated file-backed pane and the mode-`3` option-heavy pane, so it is best read for
now as one top-level non-file-backed setup branch rather than another saved-game list variant.
The setup-side file roots are tighter now too: the shared file-list builder at `0x4333f0`
formats either `saved games\\*.smp` or `maps\\*.gm*` from the shell-state fields at
`[0x006cec74+0x68/+0x6c]`, with the separate `data\\tutorial` root only appearing on the
tutorial-side `[shell+0x6c] == 2` branch. That means the `Setup.win` submode families are no
longer one generic file pane: the ordinary setup-backed `.smp` family is broader than the
narrower file-list pane, because modes `3/4/5/6/10/12/14` stay on the ordinary saved-game side
while only `4/6/9/10/12/14` re-enter the dedicated file-list panel at `0x5027b0`; the `maps`
branch is the narrower setup or tutorial launch family above the same shared record builder.
- Evidence: function-map map/scenario rows, analysis-context exports for `0x00445ac0`, `0x00445de0`,
`0x00443a50`, `0x00434300`, and `0x00444dd0`, plus objdump string and mode-table evidence for
`.gmp`, `.gmx`, `.gmc`, `.gms`, `.gmt`, `.smp`, `Quicksave`, the `0x004dd010` mode table at
@ -276,6 +460,10 @@ transition.
callback `0x595bc0`, while
`multiplayer_transport_route_callback_table_service_receive_decode_state_machine` `0x5908c0`
is the current live receive/decode state machine serviced by `0x591290` in table states `2/3`.
The callback-owner mode split above that runtime is now explicit too: append-notify `0x590370`
publishes mode `0`, compact upsert `0x590d00` publishes mode `1`, remove-notify `0x590430`
publishes mode `2`, and the live receive/decode path `0x5908c0` publishes modes `6`, `5`, and
`3`.
The route-handle lifecycle above that decode path is tighter now too: `0x590740` cleanly resets
one table's live route plus decode-side runtime without destroying the outer object; `0x5907a0`
is the broader destroy path that also releases the active descriptor collection; `0x590ed0`
@ -303,8 +491,18 @@ transition.
in `0x595bc0` reads the same `+0x0c/+0x10/+0x18` metadata triplet and replay modes later consume
the pointer through `0x5933a0`. The negative result is stronger too: local text-side xrefs still
show no direct store to `[transport+0x1778]`, and a wider local sweep also failed to show any
obvious `lea`-based replay-band writer, so the sidecar writer remains upstream of this leaf
publisher. Mode `0` is now also tied more cleanly to the generic descriptor append-notify lane
obvious `lea`-based replay-band writer. The transient-request lifecycle tightens that further:
`0x593330/0x593370/0x593380/0x5934e0/0x5933a0` now fully bound `[transport+0x1780]`, `0x1784`,
and `0x1788` without ever touching `[transport+0x1778]`, and the neighboring active-opcode reset
helper `0x5929a0` is likewise scoped only to `[transport+0x17fc]`. A broader constructor and
teardown pass tightened that further too: `0x596090`, `0x5961b0`, and `0x5962e0` all touch the
neighboring replay-band fields without ever seeding `[transport+0x1778]`. A full-binary
literal-offset sweep tightens it further still: the only direct `0x1778` hit in `RT3.exe` is
the read in `0x595bc0`. One nearby ambiguity is now closed too: the
mode-`5` mirror path in `0x595a40` and `0x595e10` does not target `[transport+0x1778]`; it
writes `[transport+0x54]` and mirrors the same staged route companion dword only into queue-side
slot `[transport+0x1724+0x24]` through `0x005a0940`. So the sidecar writer remains upstream of this
leaf publisher. Mode `0` is now also tied more cleanly to the generic descriptor append-notify lane
at `0x590370`, while mode `2` stays outside this helper as the separate
remove-notify-and-stage path at `0x590430`. The opcode-`2` payload boundary is tighter too:
`0x592ae0` now grounds that payload
@ -314,6 +512,10 @@ transition.
receive-state owner callbacks emitted by `0x5911e0 -> 0x5908c0`, not loose generic replay
guesses. So those paths are better read as delayed metadata replays over one cached work record,
not over a separate anonymous cache blob. The neighboring
capacity-owner split is tighter now too: `0x595bc0` only stages descriptor records for modes
`0`, `3`, and `5`; the upstream route-callback-table owner still delivers modes `1`, `2`, and
`6`, but those are explicit no-ops in this capacity leaf. So the owner wiring itself is no
longer the open edge; only the upstream sidecar producer remains unresolved. The neighboring
work queue is tighter too: `0x593330/0x593370/0x593380` now bound `[transport+0x1780]` as the
construct/clear/destroy owner family, while `0x5933a0`, `0x5934e0`, and `0x593570` ground the
remove, allocate, and completion side over that same collection. The small sibling `0x593400` is
@ -335,11 +537,13 @@ transition.
remove-notify-and-stage lane, `0x590490` releases the staged list, and `0x5904d0` releases the
active descriptor collection before tearing that staged list down. That also makes the earlier
`0x5962e0` “release active descriptors” step explicit. The callback-table attach side now constrains the
same work-record metadata family a little further too: `0x593650` deliberately duplicates one
caller metadata dword into both fields `+0x0c` and `+0x18`, while preserving the remaining
caller callback function pointer in `+0x10`. The lower opcode wrappers are tighter now too:
`0x592a40` and `0x592a70` both consume that staged triplet in the order `( callback fn +0x10,
callback companion +0x18, drain context id +0x0c )`. The producer side is tighter too:
same work-record metadata family a little further too: `0x593650` deliberately duplicates its
first caller metadata dword into both fields `+0x0c` and `+0x10`, while carrying the second
caller metadata dword in `+0x18`. The lower opcode wrappers are tighter now too: `0x592a40`
turned out to be the explicit opcode-`1` trigger wrapper whose constructor is a no-op and whose
active-side service is `0x5913c0`, while `0x592c40` is the real `0x08`-byte explicit opcode-`5`
binding leaf. The earlier opcode-`4` read was just the table-indexing mistake in `0x5928a0`:
selector `4` lands on the row at `0x5e2044`, not the row at `0x5e2034`. The producer side is tighter too:
bound-route requests, selector-text route requests, and the type-`9` text fastpath also stage
that same triplet through `0x5934e0`, and the fastpath shim `0x593d00` now gives the cleanest
proof of the callback split by only re-emitting the follow-on lane when `+0x10` is nonnull and
@ -351,19 +555,29 @@ transition.
`1` just before the first immediate mode-`3` snapshot. The nearby route-callback-table
lifecycle is tighter now too: `0x596090` seeds `[transport+0xba0]` as the callback-plumbing
enable latch, clears staged payload slot `[transport+0xb50]`, and constructs the three owner
branches rooted at `[transport+0xba4]`, `[transport+0x1164]`, and `[transport+0x18bc]`. The
branches rooted at `[transport+0xba4]`, `[transport+0x1164]`, and `[transport+0x18bc]`;
`0x596210` is the recurring service sweep over those same three tables plus the local field
cache and queued-descriptor family; `0x596060` is the explicit `gsi_am_rating` reset; and
`0x596530` is the reopen-from-stored-label sibling above that same am-rating table. The
matching local cleanup is tighter too: `0x5962c0` is the explicit staged route-callback payload
clear on `[transport+0xb50]`, while `0x595ce0` now clearly resets only the capacity-descriptor
route callback table at `[transport+0x1164]`, not the field-subscription table at
`[transport+0xba4]`. The remaining gap on the capacity side is
therefore narrower: mainly the still-unrecovered writer that stages `[transport+0x1778]`. The
carried sidecar fields themselves now read more cleanly as the cached callback-wrapper triplet
reused elsewhere (`drain context id +0x0c`, `callback fn +0x10`, `callback companion +0x18`),
and the negative result is stronger too: nearby replay-band fields `[transport+0x176c]`,
`[transport+0xba4]`. The remaining gap on the capacity side is therefore narrower: the carried
sidecar fields themselves now read more cleanly as the cached callback-wrapper triplet reused
elsewhere (`drain context id +0x0c`, `callback fn +0x10`, `callback companion +0x18`), and the
negative result is stronger too: nearby replay-band fields `[transport+0x176c]`,
`[transport+0x1770]`, `[transport+0x1774]`, `[transport+0x177c]`, `[transport+0x1780]`, and
`[transport+0x1784]` all have direct local owners while `[transport+0x1778]` still appears only
as the single read in `0x595bc0`. So the remaining writer looks upstream and indirect rather
than like one missing ordinary field store in the local cluster. The adjacent staged-route
as the single read in `0x595bc0`; even the broader callback-owner lifecycle now skips it while
seeding, servicing, resetting, reopening, or tearing down those neighboring tables and caches.
The constructor now closes that local search further: `0x58dc50` bulk-zeroes the full transport
body and still never writes a nonzero value into `[transport+0x1778]` before later explicit
neighbor initialization. The callback-binding owner stack now tightens that boundary too:
`0x5934e0` stages the shared work-record metadata triplet, `0x593650` binds it into the
callback-table worker path, and `0x593570` later consumes and republishes it, while
`[transport+0x1778]` still appears only as the borrowed sidecar read in `0x595bc0`. So this
edge is now locally closed, and the remaining producer looks like an upstream callback or worker
handoff rather than one missing ordinary field store in the local cluster. The adjacent staged-route
callback side is tighter too: `0x595860` is now bounded as the
submit-result handler beneath `0x5958e0`, and the old `[transport+0xac0]` ambiguity there is now
gone. That branch is using the already-grounded third selector-generation counter at `[0xac0]`
@ -424,7 +638,7 @@ transition.
callback-marshaling wrappers `0x591480` and `0x591510`, not read through any dedicated semantic
accessor yet. The route-event dispatcher side is tighter too: the mode-`5` tails in both
callback families do not copy a descriptor-local field but instead mirror the transport-staged
companion dword at `[this+0x490]` into `[this+0x54]` and the local field-cache family. The
companion dword at `[this+0x490]` into `[this+0x54]` and queue-side slot `[this+0x1724+0x24]`. The
`gsi_am_rating` maintenance lane is tighter now too: after pruning failed descriptors it sorts
the surviving primary-endpoint table through `0x590310` in mode `1` with key `gsi_am_rating`,
then selects the new head through `0x590480` before re-entering the route-transition path. The
@ -492,7 +706,7 @@ transition.
queued `gsi_am_rating` split, mode `1` for the ready-bit plus queued fallback, mode `2` for
pending-descriptor cleanup, mode `3` for the empty-table fallback, mode `4` for deferred
route-status recovery, and mode `5` for copying the staged route companion dword into `[this+0x54]`
and the local field cache. The current grounded mode transitions still switch by releasing route
and queue-side slot `[this+0x1724+0x24]`. The current grounded mode transitions still switch by releasing route
objects through `multiplayer_gamespy_route_release_and_free` and rebuilding them through
`multiplayer_transport_try_connect_live_route`, not by mutating callback slots in place. The
parser behavior is now tighter as well: semicolon lines only dispatch when
@ -553,13 +767,43 @@ transition.
stepper `simulation_advance_to_target_calendar_point`, but current grounded callers put that
helper inside the larger post-load generation pipeline `world_run_post_load_generation_pipeline`
at `0x004384d0` under the `Seeding Economy...` phase rather than under the ordinary player-facing
speed buttons. That setup pipeline is now clearer at the progress-banner level too: localized id
`318` `Computing Transportation and Pricing...` stays visible while the pipeline runs
speed buttons. That setup pipeline is now clearer at the progress-banner level too: on the fuller
setup path it first runs one preliminary named-candidate availability prepass through `0x00437743`
before any visible progress banner is posted. After that, localized id `318`
`Computing Transportation and Pricing...` stays visible while the pipeline runs
`world_compute_transport_and_pricing_grid` `0x0044fb70`, the early collection-owned staging pass
`world_setup_building_collection_phase` `0x0041ea50`, and the conditional region pair
`world_region_collection_seed_default_regions` `0x00421b60` plus
`world_region_border_overlay_rebuild` `0x004882e0`; only then does the code post id `319` `Setting
up Players and Companies...`. That `319` lane is no longer just a shell-state placeholder: its
`world_region_border_overlay_rebuild` `0x004882e0`; that border pass is now tighter too: the
outer owner refreshes the companion region set `0x006cfc9c` through the reset-and-assign wrapper
`0x00487650` above the heavier record initializer `0x00487540`, then re-enters `0x004881b0` to
refresh the raw per-region cell-count band from the live world raster, and the inner emitter
`0x00487de0` clears prior chunked segment queues through `0x00533cf0`, scans the live region
raster, and appends fresh border-segment records through `0x00536ea0`. The lower presentation
helper strip under the same owner is now explicit too: `0x00533970/0x00533980` query the cached
world-grid X/Y maxima, `0x00533ae0/0x00533af0/0x00533b00` expose the secondary-raster and
companion byte-raster roots, and `0x00533b20/0x00533b30/0x00533b70/0x00533b90` expose the
normalized coordinate, strip-offset, and sample-triplet tables used by shell-side overlay
staging. If shell-state gate
`[0x006cec74+0x174]` is set it then posts id `320` `Setting Up Buildings...` for
`world_region_collection_run_building_population_pass` `0x00421c20`; if `[0x006cec74+0x178] > 0`
it then posts id `321` `Seeding Economy...` for `simulation_run_chunked_fast_forward_burst`
`0x00437b20`; only after those setup-side gates does the code post id `319`
`Setting up Players and Companies...`. That `319` lane is no longer just a shell-state placeholder: its
earlier hidden prepass is tighter now too: `0x00437743` is the scenario-side named
candidate-availability seeding pass over the live candidate pool `0x0062b268`, feeding the
override collection at `[state+0x66b2]` through `0x00434f20` before any visible banner is posted.
That candidate-side table now has a grounded fixed record layout too: each entry is a `0x22`-byte
blob with a zero-terminated candidate-name slot at `[entry+0x00..+0x1d]` and one trailing
availability dword at `[entry+0x1e]`, read through `0x00434ea0` and mirrored later into
`[candidate+0x7ac]`. The same scenario state keeps a locomotive-side sibling collection at
`[state+0x66b6]`, read through `0x00435030` and updated through `0x004350b0`, which is now the
shared named locomotive-availability lane beneath the `Locomotives` editor page and the
startup-side locomotive seeding branches. That locomotive-side table is the same pattern at a
larger width: each entry is a `0x41`-byte blob with a zero-terminated locomotive-name slot at
`[entry+0x00..+0x3c]` and one trailing availability dword at `[entry+0x3d]`, later mirrored into
`[loco+0x7b]`. Both override dwords now read most safely as simple availability bits rather than
wider mode enums. That `319` lane is no longer just a shell-state placeholder: its
primary grounded work is still the chairman-profile pair
`world_seed_default_chairman_profile_slots` `0x004377a0` plus
`world_build_chairman_profile_slot_records` `0x00437220`, which seed the 16 selector bytes at
@ -582,8 +826,12 @@ transition.
surface beside that chairman panel is clearer now too.
`map_editor_scenario_metadata_panel_refresh_controls` `0x004ca790` republishes the scenario
description from `[0x006cec78+0x672e]`, the start-year trio `[+0x66ca]`, `[+0x66d2]`, and
`[+0x66ce]`, and the paired boolean toggles `[+0x66de]` plus inverse `[+0x66f3]` across control
band `0x5b69..0x5b74`, while `map_editor_scenario_metadata_panel_refresh_briefing_mode`
`[+0x66ce]`, the direct campaign-designated bit `[+0x66de]` through control `0x5b6e`, and the
inverse of the paired metadata byte `[+0x66f3]` through control `0x5b74`. The resource-side
anchor is now explicit too: `editorDetail.win` carries localized ids `3160/3161` `Campaign
Scenario` and `If checked, this map will be reserved as a campaign scenario.` inside the control
record rooted at `0x5b6e`, so `[+0x66de]` is now the grounded campaign-scenario flag rather than
an anonymous metadata boolean. `map_editor_scenario_metadata_panel_refresh_briefing_mode`
`0x004ca670` now bounds the single-player versus multiplayer briefing switch by flipping selector
`0x621f50`, publishing localized headings `1491` and `3586`, and refreshing the two briefing texts
from `[state+0x4f30]` and `[+0x5ae9]`. The companion dispatcher
@ -695,10 +943,24 @@ transition.
longer just an abstract issue table lookup because its merger callsite uses issue id `0x3a`, which
lines up directly with localized id `726` saying merger votes depend on public attitude toward the
management of the two companies. By contrast the broader support-adjusted share-price helper
`company_compute_public_support_adjusted_share_price_scalar` `0x00424fd0` uses the broader issue
id `0x37`, which currently looks like a more general company-management or public-sentiment slot
rather than the merger-only attitude term. The supporting stat layer is bounded more cleanly now
too: the
`company_compute_public_support_adjusted_share_price_scalar` `0x00424fd0` uses issue id `0x37`,
while the finance-side debt helpers now bound `0x38` and `0x39` separately as the explicit
credit-rating and prime-rate lanes. That leaves `0x37` as the broader investor-confidence lane
behind equity support, share price, and adjacent governance pressure, with the strongest current
text anchors coming from the investor-attitude strings `1217` and `3048/3049` about company or
chairman performance rather than from the merger-only management-attitude term. One older local lead is now ruled out too: the
`0x460a90` / `0x473620` setup block is the camera-view hotkey family over localized ids
`3482..3489` (`Select/Assign Camera View 5..8`), not issue-opinion infrastructure, so it should
no longer be used as evidence for the player-facing meaning of issue `0x37`. The editor-side
`Stock Prices` label is also no longer being used as direct evidence here: the `0x4ca980` /
`0x4cadf0` panel owns a separate float-tuning block `[state+0x0bde..0x0bf6]`, with
`[state+0x0bde]` merely mirroring `[state+0x0be2]`, so that label belongs to a different
settings family than the issue table behind `0x37`. A direct shell-resource follow-up now narrows
the remaining caption question too: the extracted `CompanyDetail.win` blob from `rt3_2WIN.PK4`
contains no plain-English investor or finance caption for this lane, which matches the owner-side
read that section-0 is a dynamic `0x947f` text widget fed by
`shell_format_company_governance_and_economy_status_panel` `0x004e5cf0` rather than a separate
fixed label row. The supporting stat layer is bounded more cleanly now too: the
surrounding `0x0b` setup in the merger and takeover offer builders is formatter mode rather than a
player-facing issue number, while the company-side stat wrapper
`company_read_year_or_control_transfer_metric_value` `0x0042a5d0` now reads as a generic
@ -722,14 +984,43 @@ transition.
`world_region_collection_run_building_population_pass` `0x00421c20` plus the deeper per-region
worker `world_region_balance_structure_demand_and_place_candidates` `0x004235c0`, while
`[0x006cec74+0x178]` directly fronts id `321` `Seeding Economy...` and the chunked burst helper
`simulation_run_chunked_fast_forward_burst`; id `322` then fronts `Calculating Heights...`. The
`simulation_run_chunked_fast_forward_burst`, whose grounded tail now also sweeps the live region
collection through `world_region_refresh_cached_category_totals_and_weight_slots` `0x00423d30`;
id `322` then fronts `Calculating Heights...`. The
master `+0x68` flag is no longer just structural: the shell load/save coordinators now use the
same flag to force the editor-map `.gmp` family, so current evidence treats it as the broader
editor-map mode above those later setup branches rather than an unnamed generic toggle. That
worker is no longer one opaque building bucket: current grounded categories split into `House`, a
weighted region-profile family surfaced through the `Industry Weightings` stats path, and a third
branch whose low-level fallback token is `Commercial` but whose aligned stats label is `City
Support`. The same lower helper also reappears later on a slower simulation-side cadence with
Support`. The same placement-commit gate beneath it, `world_region_validate_and_commit_candidate_placement`
`0x00422a70`, is also corroborated by the separate world-side randomized batch helper
`world_try_place_random_structure_batch_from_compact_record` `0x00430270`, which retries
placements around one compact center/radius record rather than the ordinary per-region demand
deficits. That batch placer now sits under a wider compact runtime-effect dispatcher,
`world_apply_compact_runtime_effect_record_to_resolved_targets` `0x00431b20`, so the world-side
branch is no longer just “another caller near `0x43051e`” but one real effect family alongside
the ordinary region-demand worker. Above that, the live scenario event collection at `0x0062be18`
now has a tighter runtime-effect lane too: `scenario_runtime_effect_record_service_and_dispatch_linked_compact_effects`
`0x004323a0` services one live runtime-effect record, dispatches its linked compact effects
through `0x00431b20`, and can synthesize follow-on records through
`scenario_runtime_effect_record_build_followon_effect_from_compact_record_and_targets`
`0x00430b50`, which in turn allocates new live records through
`scenario_event_collection_allocate_runtime_effect_record_from_compact_payload` `0x00432ea0`.
Above that, `scenario_event_collection_service_runtime_effect_records_for_trigger_kind`
`0x00432f40` now bounds the collection-wide loop that services those live runtime-effect records
for one trigger kind. That trigger split is tighter now too: recurring simulation maintenance
drives kinds `1`, `0`, `3`, and `2`; the neighboring route-style follow-on drives `5` and `4`;
startup-company and named-railroad creation branches drive `7`; kind `6` is now bounded as a
mixed post-change family spanning the placed-structure post-create tail, one build-version-gated
company-startup or roster-refresh tail, and the route-entry post-change sweep on `0x006cfca8`;
one world-entry-side one-shot gate drives `8` and then clears shell-profile latch
`[0x006cec7c+0x97]`; the briefing-text query lane is kind `9`; and the collection dirty latch
still forces the internal rerun at kind `0x0a`.
That moves this branch out of the “isolated world-side placement oddity” bucket and into a real
scenario-runtime effect pipeline with a mostly bounded trigger-kind family.
The same lower helper also reappears later on a slower
simulation-side cadence with
scale `1/12`, so it no longer looks like one-time setup glue only. The actual game-speed control
family remains separate, rooted at `world_set_game_speed_mode` `0x00434680`,
`world_adjust_game_speed_mode_delta` `0x00434850`, and `world_toggle_pause_or_restore_game_speed`
@ -1355,7 +1646,10 @@ transition.
current anchor site, then either appends that entry through `0x004b3160` and refreshes the new
trailing selection through `0x004b2f00`, or rotates one existing slot in place when the local
two-entry cap has already been reached. So this edge now reaches an actual train-side autoroute
append lane rather than stopping at anonymous company-side cache cells.
append lane rather than stopping at anonymous company-side cache cells. The weighted cache lanes
still do not escape that route-choice family directly: this train-side append path only inherits
the weighted site and peer choice by calling `0x00408380`, not by reading cache `+0x0e/+0x16`
itself.
The train-side follow-on above that seed path is bounded now too. The owning company can count
its live roster through `company_count_owned_trains` `0x004264c0`, measure one aggregate linked
transit site pressure through `company_compute_owned_linked_transit_site_score_total`
@ -1367,7 +1661,9 @@ transition.
branch when exactly two eligible linked transit sites survive.
Because it consumes `+0x12` rather than `+0x0e` or `+0x16`, current evidence now says the tracker
compatibility split is more important for seeded route choice and ranked site choice than for the
final company train-count target itself.
final company train-count target itself. The local linked-transit chain is now bounded enough to
say that directly: weighted cache lanes feed `0x00408280 -> 0x00408380 -> 0x00409770/0x00409830`,
while the separate pressure or roster lane feeds `0x00408f70 -> 0x00409950` from raw `+0x12`.
The balancer then applies two age bands to company-owned trains:
very old trains are removed when the roster already exceeds target or upgraded when it still
needs capacity, while the mid-age band can trigger one narrower upgrade pass.
@ -1469,12 +1765,16 @@ transition.
`[+0x4a8b]` and `[+0x4a87]` clear, at least two bond slots live, and at least one year since
founding. It derives one issue batch from outstanding shares rounded down to `1000`-share lots
with floor `2000`, trims that batch until the broader support-adjusted share-price scalar times
batch no longer exceeds the `55000` gate, requires that scalar at least `22`, resolves the
highest-coupon live bond slot, and then uses current cash from `0x2329/0x0d` as a gate against
that slot's principal plus a small fixed buffer before it compares the chosen bond-rate lane
against a normalized scalar ratio built from the same support-adjusted share-price lane and
current `Book Value Per Share` from `0x2329/0x1d` through the piecewise approval ladder
`0.07/1.3 -> 0.14/0.35`. On success it issues two
batch no longer exceeds the `55000` gate, recomputes the pressured support-adjusted share-price
scalar and the paired `price/book` ratio, then tests the remaining gates in a fixed order:
share-price floor `22`, proceeds floor `55000`, current cash from `0x2329/0x0d` against the
chosen highest-coupon bond principal plus `5000`, one later stock-issue cooldown gate that
converts the current issue mixed-radix calendar tuple at `[company+0x16b/+0x16f]` through
`calendar_point_pack_tuple_to_absolute_counter` `0x0051d3c0` and compares the result against the
active world absolute calendar counter `[world+0x15]`, and only then the coupon-versus-price-to-book
approval ladder `0.07/1.3 -> 0.14/0.35`. The issue mutator preserves the previous tuple in
`[company+0x173/+0x177]` and refreshes the current tuple from `[world+0x0d/+0x11]` on the
derived-pricing lane. On success it issues two
same-sized tranches through repeated `company_issue_public_shares_and_raise_capital` calls and
publishes a separate equity-offering news family rooted at localized id `4053`, not the earlier
debt or buyback headline family.
@ -1615,24 +1915,149 @@ transition.
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 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
`[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. The `319` lane itself is no longer the
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 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 `[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. 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`,
then a flagged world-grid cleanup sweep through `0x00448af0/0x00533fe0`, and only after that the
later route-entry post-pass at `0x00491c20`. The same later lane now also reaches a separate
event-side runtime branch: the live event collection at `0x0062be18` re-enters
`scenario_event_collection_refresh_runtime_records_from_packed_state` `0x00433130`, which in
turn materializes each live event record through
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:
before that later world and shell reactivation tail, `world_entry_transition_and_runtime_bringup`
runs one distinct post-bundle status and runtime refresh phase that posts progress ids `0x196`
and `0x197` through `0x005193f0/0x00540120` with paired `0x004834e0` follow-ons, refreshes the
live event collection at `0x0062be18` through
`scenario_event_collection_refresh_runtime_records_from_packed_state` `0x00433130`, rebuilds the
scenario-side port-or-warehouse cargo recipe runtime tables through `0x00435630`, and then runs
the named-candidate availability preseed through `0x00437743`. 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 latch `[profile+0x97]` is set, mirrors the
grounded campaign-scenario bit `[profile+0xc5]` and sandbox bit `[profile+0x82]` into world
bytes `[world+0x66de]` and `[world+0x66f2]`, restores the selected year/profile lane through
`[profile+0x77]` into `[world+0x05/+0x09/+0x15]` through
`world_set_selected_year_and_refresh_calendar_presentation_state` `0x00409e80`; that restore now
has the explicit companion `world_refresh_selected_year_bucket_scalar_band` `0x00433bd0`, which
rebuilds the dependent selected-year bucket floats after the packed year changes; 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
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. 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, and 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
`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
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. 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`,
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, 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 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 event
side is tighter too:
that `0x00433130` pass in turn materializes each live event record through
`scenario_event_refresh_runtime_record_from_packed_state` `0x0042db20`. Current shell-side xrefs
now tighten that event branch too: the first rebuilt linked row family under `0x0042db20` aligns
with the standalone condition list later queried by `EventConditions.win`, while the second
@ -1754,18 +2179,31 @@ transition.
`company_compute_cached_recent_per_share_performance_subscore`,
`company_compute_five_year_weighted_shareholder_return`, and
`company_compute_public_support_adjusted_share_price_scalar` bound the recent per-share
performance and investor-support/share-price blend beneath those vote resolvers,
performance and investor-support/share-price blend beneath those vote resolvers; the recent
per-share feeder now has a grounded four-lane tail too, with current partial-year weight
`(5 * [world+0x0f]) - 5`, prior full-year weights `48/36/24/12` on `0x1f/0x1e`, dividend
non-decline pair weights `9/8/7/6` on `0x20`, lane weights `40/10/20/30`, the startup age ramp
`0/0/0/100 -> 25/25/35/100 -> 50/50/65/100 -> 75/75/85/100 -> 100/100/100/100`, a strongest-lane
`*1.25` boost, a weakest-lane `*0.8` reduction, and separate bounded-intermediate versus final
difficulty applications under `0x005f33b8`; the next consumer `0x00424fd0` is also tighter now,
with the young-company interpolation against `[company+0x57]`, caller pressure clamped to
`[-0.2, 0.2]`, one `(shares / 20000)^0.33` share-count growth term, and the later threshold
ladder `0.6 / 0.45 / 0.3 / 1.7 / 2.5 / 4.0 / 6.0` before the issue-`0x37` multiplier,
`scenario_state_compute_issue_opinion_multiplier` now bounds the
next layer of optional company, chairman, and territory-specific opinion overrides on the active
scenario state, and the broader stat-reader family around
`company_read_control_transfer_metric_slot` and
`company_read_year_or_control_transfer_metric_value` is no longer just a merger-premium helper.
Current grounded callers show the same metric family feeding the annual shareholder-revolt and
creditor-liquidation lane surfaced by localized ids `300..304`, so the remaining gap is now mostly
semantic: the exact player-facing names of the support-and-governance metric slots behind issue
ids `0x37` and `0x3a`, plus any later chairmanship-control side effects beyond the already
grounded success or failure commit points. The packed simulation calendar tuple semantics also
remain open. The `TrackLay.win` family now clearly owns `Lay single track.` `Lay double track.`
creditor-liquidation lane surfaced by localized ids `300..304`, while the debt-side shell and
bond lane now separately close `0x38` as `Credit Rating` and `0x39` as `Prime Rate`. That means
the remaining gap is now mostly gone on the UI side too: issue `0x37` is already bounded to the
same investor-confidence family as the equity-support and governance-pressure paths, and current
grounded UI evidence still stops at the investor-attitude sentence family rather than one
standalone caption. The calendar side is tighter now too:
`[world+0x15]` is the absolute counter for the same mixed-radix `12 x 28 x 3 x 60`
year-plus-subfield tuple packed by `0x0051d3c0` and unpacked by `0x0051d460`, not just a vague
“calendar-like” blob. The `TrackLay.win` family now clearly owns `Lay single track.` `Lay double track.`
and `Bulldoze` as its three primary modes, its bridge selector, its wrapped frequency preferences,
and a strongly aligned pair of `Auto-Hide Trees During Track Lay` and `Auto-Show Grade During
Track Lay` toggles; the `StationPlace.win` family now clearly owns its six top-level category
@ -2055,10 +2493,16 @@ transition.
`0x0042cb30` is the final recent-service clamp over the primary per-candidate word table. Above
that refresh lane, `placed_structure_query_candidate_local_service_metrics` `0x0047e240` is the
first higher-level query, `placed_structure_count_candidates_with_local_service_metrics`
`0x0047e330` counts how many candidates currently produce that query, and
`0x0047e330` counts how many candidates currently produce that query,
`placed_structure_get_nth_candidate_id_with_local_service_metrics` `0x0047e620` is the ordinal
selector over that same visible candidate family,
`placed_structure_query_cached_express_service_class_score` `0x0047e390` caches one parallel class
score for the express family now strongly aligned with `Passengers`, `Mail`, and `Troops`. Those
site-side scores now have grounded shell read-side consumers too:
score for the express family now strongly aligned with `Passengers`, `Mail`, and `Troops`,
`placed_structure_refresh_candidate_local_service_comparison_cache_against_peer_site`
`0x0047eb90` rebuilds one peer-site comparison cache over the same local-service inputs, and
`placed_structure_select_best_candidate_id_by_local_service_score` `0x0047f910` is the best-hit
selector above the direct and directional local-service query pair. Those site-side scores now
have grounded shell read-side consumers too:
`shell_station_detail_format_freight_and_express_summary` `0x00506be0` formats the visible
`Freight: %1` and `Express: %1` lines in `StationDetail.win`, and the same station-detail family
now has a deeper candidate-service lane: