rrt/docs/control-loop-atlas.md

2190 lines
188 KiB
Markdown
Raw Normal View History

# Control-Loop Atlas
This atlas is the high-level map for RT3 1.06. It is intentionally broader than the function map:
each section explains who owns a loop, where it starts, what dispatches it, which state blocks
anchor it, and where control is handed to neighboring subsystems.
Subsystem notes now live under [docs/atlas](/home/jan/projects/rrt/docs/atlas/README.md) for
faster navigation. The longform atlas remains the canonical narrative reference during this
transition.
## CRT and Process Startup
- Roots: `entry` at `0x005a313b`, CRT helpers in the `0x005a2d..0x005ad4..` range, and
`app_bootstrap_main` at `0x00484440`.
- Trigger/Cadence: single process startup path before shell or engine services exist.
- Key Dispatchers: `startup_init_tls_state`, `startup_init_file_handle_table`,
`startup_run_init_callback_table`, `__setenvp`, `startup_build_argv`,
`___crtGetEnvironmentStringsA`, then `app_bootstrap_main`.
- State Anchors: CRT heap and file-handle tables; process environment and argv storage.
- Subsystem Handoffs: exits the generic CRT path at `app_bootstrap_main`, which becomes the first
RT3-owned coordinator.
- Evidence: `artifacts/exports/rt3-1.06/startup-call-chain.md`,
`artifacts/exports/rt3-1.06/function-map.csv`.
- Open Questions: exact ownership boundary between compiler CRT shims and the first game-owned
bootstrap helper; whether any nontrivial startup callbacks seed game globals before
`app_bootstrap_main`.
## Bootstrap and Shell Service Bring-Up
- Roots: `app_bootstrap_main` at `0x00484440`, `bootstrap_init_shell_window_services` at
`0x004840e0`, and `shell_install_global_controller` at `0x0051ff90`.
- Trigger/Cadence: one-time bootstrap handoff immediately after CRT completion.
- Key Dispatchers: `app_bootstrap_main`, `bootstrap_init_shell_window_services`,
`shell_install_global_controller`, `shell_service_pump_iteration`, graphics config load or
default-init helpers, runtime capability probes, and early shell service initializers under the
`0x004610..0x0053f0..` branch.
- State Anchors: global shell controller pointer `0x006d4024`, sibling display/runtime globals under
`0x006d402c` and `0x006d4030`, and host capability flags gathered by
`bootstrap_probe_system_profile`.
- Subsystem Handoffs: after the global shell controller has been installed the bootstrap path enters
the repeating `shell_service_pump_iteration` loop, which services shell-state work and hands each
iteration down into the controller frame path; when the shell lifetime ends this same bootstrap
path tears the shell bundle down and returns to `app_bootstrap_main`.
- Evidence: `startup-call-chain.md`, function-map rows for `app_bootstrap_main`,
`bootstrap_init_shell_window_services`, `shell_install_global_controller`,
`shell_service_pump_iteration`, `shell_load_graphics_config_or_init_defaults`,
`shell_reset_display_runtime_defaults`, and related graphics setup helpers.
- Open Questions: whether gameplay or in-engine world stepping later escapes this bootstrap-owned
shell loop entirely, or whether gameplay entry still rendezvous with the same outer coordinator
before the shell bundle is destroyed.
## Shell UI Command and Deferred Work Flow
- Roots: shell callback paths that converge on `shell_dispatch_ui_command` at `0x00464410`.
- Trigger/Cadence: event-driven UI command dispatch plus deferred-message queue flushing during
shell activity.
- Key Dispatchers: `shell_dispatch_ui_command`, `shell_enqueue_deferred_work_message`,
`shell_post_deferred_message_type5`, `shell_post_deferred_message_type6`,
`shell_enqueue_deferred_message_type4`, `shell_enqueue_deferred_message_type1`.
- State Anchors: shell object at `0x0062be68`, queue roots around `[this+0x11369d]`,
`[this+0x1136a1]`, and `[this+0x1136a5]`, global routing gates at `0x006d4034`, and the separate
detail-panel controller rooted at `0x006d0818`.
- Subsystem Handoffs: routes into graphics config, scenario-text export, overlay generation,
multiplayer UI, shell detail windows such as `EditorPanel.win` and `TrainDetail.win`, and
presentation-facing deferred work later drained by `shell_service_frame_cycle`.
- Evidence: function-map shell rows around `0x00464410`, `0x004d4500`, `0x004ddbd0`, and
`0x0051f1d0..0x0051f460`.
- Open Questions: whether the shell command dispatcher is also used by hotkeys or only by UI
callback tables; the current `0x006d0818` detail-panel path looks shell-only and does not yet
explain gameplay world entry.
## Presentation, Overlay, and Frame Timing
- Roots: the bootstrap-owned `shell_service_pump_iteration` at `0x00483f70`, the shell-state service
pass `shell_state_service_active_mode_frame` at `0x00482160`, the installed global shell
controller at `0x006d4024`, the pending frame-cycle owner `shell_service_frame_cycle` at
`0x00520620`, and the frame-time history path under `shell_update_frame_time_history` at
`0x0051fd70`.
- Trigger/Cadence: recurring bootstrap-owned shell service work once the active mode, controller
window, and display runtime are live; special modal or content-building paths can also force
immediate frame servicing inside that broader cadence.
- Key Dispatchers: `shell_service_pump_iteration`, `shell_state_service_active_mode_frame`,
`shell_service_frame_cycle`, `shell_refresh_presentation_frame`,
`shell_update_frame_time_history`, `shell_get_smoothed_frame_scalar`,
`shell_set_gamma_ramp_scalar`, and overlay builders such as
`shell_queue_single_world_anchor_overlay`, `shell_queue_world_anchor_overlay_list`, and
`shell_queue_indexed_world_anchor_marker`.
- State Anchors: shell state at `0x006cec74`, active mode pointer `0x006cec78`, shell frame history
ring at `0x006d403c`, display/runtime state inside the controller block near `[this+0x114282]` and
`[this+0x11428a]`, presentation service pointer at `[this+0x0c]`, and the native controller window
handle at `[this+0x00]`.
- Subsystem Handoffs: the bootstrap-owned pump runs shell-bundle polling and shell-state maintenance
before the shell-state pass synchronizes active-mode helpers and modal-status work and dispatches
the controller frame cycle, which then consumes world/object state for overlays and presentation
refresh, uses the controller window handle for one-time `ShowWindow` and related UI interaction,
and drains the deferred work queues at the end of the cycle.
- Evidence: function-map rows for `shell_service_pump_iteration`,
`shell_state_service_active_mode_frame`, `shell_service_frame_cycle`,
`shell_flush_deferred_work_queues`, frame history, gamma ramp, world-anchor overlay builders, and
graphics runtime helpers.
- Open Questions: how simulation cadence rendezvous with the shell presentation cadence once
gameplay takes over and whether gameplay stepping exits this shell-owned controller path entirely.
## Map and Scenario Content Load
- Roots: `shell_map_file_entry_coordinator` at `0x00445ac0`, 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`,
`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`.
- State Anchors: shell-side file staging buffers at `0x0062bee0` and `0x0062bec4`, shell and mode
globals at `0x006cec74` and `0x006cec78`, world object root `0x0062c120`, map bundle state
allocated through `0x00530c80`, and geography tables rooted at `0x0062b2fc` and `0x0062b268`.
- Subsystem Handoffs: the shared `fileopt.win` dialog rooted at `0x004dc670` now looks like the
shell-side selector above the two broad file coordinators. Its message handler sets `0x006d07f8`
for the load or restore side or `0x006d07ec` for the save or package side before the detail-panel
transition manager routes into `shell_map_file_entry_coordinator` or
`shell_map_file_world_bundle_coordinator`. The former unresolved third flag at `0x006d07f0` is now
accounted for too: it escapes into the standalone `SettingsWindow.win` path through
`shell_open_settings_window` rather than another map or save verb. The broad coordinators now hand
their interactive work through the shared `filerqst.win` helper at `0x004dd010`, and that helper
gives the extension split a firmer shape. The paired editor-map path is now grounded as `.gmp`
through load mode `4` and save mode `3`. The remaining non-editor families are no longer anonymous
either: `.gmc` is the campaign-scenario branch, backed both by the campaign-screen resignation
prompt on `0x006cec7c+0xc5` and by the numbered `%s%02d.gmc` save helper at `0x00517c70`; `.gmx`
is the sandbox branch, backed by the shell-side `The briefing is not available in sandbox games.`
restriction on `0x006cec7c+0x82`; and the default `.gms` branch is therefore the standalone
scenario family. When a live runtime world is already active the same helper bypasses those
non-runtime extensions and forces the `.smp` runtime-state branch instead. The auxiliary save-side
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.
- 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
`0x005f3d58`, the auxiliary-owner presence check at `0x00434050`, and the `.gmt` handoff through
`0x00469d30`, together with localized string evidence from ids `3018` and `3898`.
- Open Questions: bit `0x1` on both broad coordinators now grounds the Quicksave name seed and the
former third `fileopt.win` flag has been ruled out as a file-flow question because it just opens
`SettingsWindow.win`. The old broad extension question is mostly resolved: `.gmp` is the
editor-map pair, `.gms` is the standalone scenario family, `.gmc` is the campaign-scenario family,
`.gmx` is the sandbox family, and `.gmt` is at least bounded as an auxiliary preview-surface
branch rather than another gameplay save family. The higher-value global question is no longer
whether `0x00443a50` is world entry. It is where the long-lived simulation cadence takes over
after this bring-up and whether that cadence still rendezvous with the shell-owned frame path or
escapes into a separate gameplay loop.
## Multiplayer Session and Transport Flow
- Roots: `multiplayer_window_init_globals` at `0x004efe80`, `multiplayer_window_service_loop` at
`0x004f03f0`, the Multiplayer.win session-event callback table built by
`multiplayer_register_session_event_callbacks` at `0x0046a900`, the active session-event transport
object at `0x006cd970`, the Multiplayer preview dataset object at `0x006cd8d8`, and the lower
pending-template and text-stream helpers around `0x00597880..0x0059caf0`.
- Trigger/Cadence: shell-owned Multiplayer.win frame service plus event-driven session callbacks and
repeated transport pump steps.
- Key Dispatchers: session-event wrappers for actions `1`, `2`, `4`, `7`, `8`;
`multiplayer_register_session_event_callbacks`; `multiplayer_dispatch_requested_action`;
`multiplayer_reset_preview_dataset_and_request_action`;
`multiplayer_preview_dataset_service_frame`; `multiplayer_load_selected_map_preview_surface`;
`multiplayer_flush_session_event_transport`; `multiplayer_transport_service_frame`;
`multiplayer_transport_service_worker_once`;
`multiplayer_transport_service_route_callback_tables`;
`multiplayer_transport_service_status_and_live_routes`;
`multiplayer_transport_text_stream_service_io`;
`multiplayer_transport_dispatch_pending_template_node`;
`multiplayer_transport_service_pending_template_dispatch_store`.
- State Anchors: live session globals at `0x006d40d0`, active session-event transport object at
`0x006cd970`, status latch at `0x006cd974`, session-event mode latch at `0x006cd978`, retry
counter at `0x006cd984`, preview dataset object at `0x006cd8d8`, preview-valid flag at
`0x006ce9bc`, staged preview strings at `0x006ce670` and `[0x006cd8d8+0x8f48]`, Multiplayer.win
backing block at `0x006d1270`, selector-view store root at `[transport+0xab4]`, selector-view
generation counters at `[transport+0xab8]..[transport+0xac0]`, selector-view backing arrays around
`[transport+0xad0]..[transport+0xae4]`, selector-view entry probe-request id at `[entry+0x50]`,
live-state gate at `[entry+0x58]`, third-slot flag word at `[entry+0x64]`, probe-schedule tick at
`[entry+0x68]`, last-success tick at `[entry+0x6c]`, pending-probe latch at `[entry+0x74]`,
success generation at `[entry+0x78]`, consecutive-failure counter at `[entry+0x7c]`, rolling
average at `[entry+0x80]`, recent sample window at `[entry+0x84..]`, bounded sample-count at
`[entry+0x94]`, total-success count at `[entry+0x98]`, pending-template list at
`[transport+0x550]`, dispatch store at `[worker+0x54c]`, and text-stream buffers rooted under
`[worker+0x1c]`.
- Subsystem Handoffs: the Multiplayer.win initializer seeds the backing block at `0x006d1270`, later
reset paths construct the separate preview dataset at `0x006cd8d8`, and the shell-owned
active-mode frame services that dataset every frame through
`multiplayer_preview_dataset_service_frame`. That preview side publishes roster and status
controls through the Multiplayer window control paths, loads `.gmt` preview surfaces through
`multiplayer_load_selected_map_preview_surface`, and is even reused by the map/save coordinators
mode-`11` `.gmt` path when the dataset already exists. In parallel,
`multiplayer_register_session_event_callbacks` allocates and registers the separate session-event
transport object at `0x006cd970`. The shell-side bridge into that deeper transport cadence is now
tighter: `multiplayer_window_service_loop` and neighboring reset or initializer branches call
`multiplayer_flush_session_event_transport`, which forces one status flush and then drops into
`multiplayer_transport_flush_and_maybe_shutdown`. That wrapper in turn runs
`multiplayer_transport_service_frame`, the recurring pump that services one worker step through
`multiplayer_transport_service_worker_once`, sweeps the transport-owned callback tables and field
caches through `multiplayer_transport_service_route_callback_tables`, services both the auxiliary
status route and the current live route through
`multiplayer_transport_service_status_and_live_routes`, and then descends one layer farther into
the shared GameSpy route helper `multiplayer_gamespy_route_service_frame` at `0x58d040`. The
transport also owns a separate selector-view sidecar beneath that route cadence.
`multiplayer_transport_ensure_selector_view_store` allocates the keyed selector-view store at
`[transport+0xab4]`, `multiplayer_transport_find_selector_view_entry_by_name` resolves entries
from that store, `multiplayer_transport_upsert_selector_name_entry` marks per-slot activity and
flags inside each entry, and `multiplayer_transport_mark_selector_slot_views_dirty` plus
`multiplayer_transport_reset_selector_view_entry_runtime_state` manage the dirty or refresh fields
at `+0xa0`, `+0xa4`, and `+0xa8`. That selector-view maintenance path is now split more cleanly
too. The recurring owner is `multiplayer_transport_service_selector_view_refresh_cycle`, which
first runs the fast deferred-probe lane:
`multiplayer_transport_collect_refreshable_selector_view_entries` walks the store through
`multiplayer_transport_filter_insert_refreshable_selector_view_entry`, which now shows that
`[entry+0x64]` is not a generic flag bucket but the third selector-slot flag word, parallel to
`[entry+0x5c]` and `[entry+0x60]`. In that collector, the `g` and `a` mode-letter bits produced by
`multiplayer_transport_parse_selector_mode_letters` become mask `0x0c` in the slot-local flag
words, and any third-slot entry carrying those bits at `[entry+0x64]` is excluded from the
refreshable set. Eligible entries then pass slot-aware retry timing on `[entry+0x68]`,
`[entry+0x6c]`, `[entry+0x78]`, and `[entry+0x7c]`, after which the service loop schedules refresh
probes through `multiplayer_transport_schedule_selector_view_entry_refresh_probe`. That fast lane
is narrower now too: the entry-side match key `[entry+0x50]` is no longer just an opaque request
field. The profile-key callback lanes feed
`multiplayer_transport_parse_selector_view_probe_marker`, which decodes one local `X%sX|%d` marker
into a probe request id plus displayed version/build integer, and
`multiplayer_transport_arm_selector_view_probe_tracking` stores those into `[entry+0x50]` and
`[entry+0x54]` before arming the live probe gate at `[entry+0x58]`. The current-selector callback
root at `0x59f8b0` is now bounded as well: it resolves and upserts the active selector name,
optionally reuses a cached `username` marker to arm probe tracking immediately, then submits the
same profile-key bundle with selector context and forwards that selector through callback slot
`17`, with the status-route side able to force route-mode transitions `2 -> 3 -> 4` afterward. One
layer lower, `multiplayer_transport_handle_profile_key_query_result` at `0x596970` now bounds the
per-key result path itself. It treats `username` as the probe-marker field, `b_flags` as the
selector mode-letter field, and `(END)` as a real sentinel that publishes a zeroed slot-`22`
payload instead of a marker pair. The same helper also hashes the selector-name, key-name, and
resolved value text back into the caller table, so the profile-key bundle now looks like a real
bounded handoff rather than an anonymous callback cloud. The deferred callback shim
`multiplayer_transport_dispatch_selector_view_refresh_probe_result` then walks the keyed store
through `multiplayer_transport_finish_selector_view_refresh_probe_if_matching`, which only
completes entries whose pending latch `[entry+0x74]` is still armed and whose parsed marker
request id `[entry+0x50]` matches the finished request. A failed result `-1` clears the pending
latch and increments the consecutive-failure counter at `[entry+0x7c]`. A nonfailure result clears
the pending latch, increments the success generation at `[entry+0x78]` and total-success count
`[entry+0x98]`, clears `[entry+0x7c]`, stamps the last-success tick at `[entry+0x6c]`, appends the
returned sample into the short rolling history at `[entry+0x84..]`, grows the bounded sample-count
`[entry+0x94]` up to four, computes the current average into `[entry+0x80]`, and then publishes
that averaged `ms` sample through `multiplayer_transport_enqueue_callback_slot24_record`. So the
publication boundary is explicit and the request-id ownership is explicit: `[entry+0x80]` now
reads as the averaged millisecond probe sample and `[entry+0x54]` as the displayed version/build
companion integer. The adjacent route-callback side is tighter too, but it is now kept separate:
the staged route-callback path at `0x5958e0` and the later compatibility gate at
`multiplayer_transport_route_binding_matches_route_callback_descriptor_tuple` `0x595d00` operate
on a compact GameSpy-style server or route descriptor family with a primary endpoint tuple at
`[descriptor+0x00]/[+0x04]`, an optional secondary endpoint tuple at `[descriptor+0x08]/[+0x0c]`,
string-key lookups such as `hostname` and `gamever`, and numeric-key lookups such as
`numplayers`, `numservers`, `numwaiting`, and `gsi_am_rating`. The route-binding side uses that
descriptor family's primary dword and host-order port plus the optional secondary tuple against
route-binding offsets `+0x54/+0x58` and route word `+0x30`. Current evidence still does not prove
that descriptor tuple is the same field family as the selector-view marker companion integer at
`[entry+0x54]`. The higher compact decode owners are tighter now too: `0x5907d0` is the
allocate-and-append lane for one self-consistent compact payload, while `0x590d00` is the keyed
upsert-by-primary-endpoint lane that reuses an existing descriptor when possible and then notifies
the owner callback. The route-callback-table runtime above that decode side is tighter now too:
`multiplayer_transport_route_callback_table_construct` `0x5905e0` seeds one transport-owned
table block, `multiplayer_transport_route_callback_table_release_decoded_schema_dictionary`
`0x5906f0` tears down the decoded schema dictionary rooted at `[this+0x08]`,
`multiplayer_route_callback_runtime_acquire_shared_string_copy` `0x590540` and
`multiplayer_route_callback_runtime_release_shared_string_copy` `0x5905a0` now bound the shared
string pool used by that decoded schema, and the higher bring-up owner `0x596090` now clearly
splits between `[transport+0xba4]` with owner callback `0x595a40`, the local field-cache family
`[transport+0x1724]` seeded through `0x5a08f0/0x595b60`, and `[transport+0x1164]` with owner
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 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`
opens the live route handle into `[this+0x4a0]`, stages the initial outbound request, and seeds
state `3` plus the staged receive buffer; `0x5911e0` is the state-`2/3` socket-service wrapper
that reads new bytes, grows the staged buffer, and re-enters `0x5908c0`; `0x5912c0` is the
one-shot send-with-reopen-retry helper; and `0x590ea0` is the shared disconnect publication and
reset tail. The recurring service helper `0x591290` is tighter too: it now first clears the
staged intrusive descriptor list through `0x590490` before entering the state-driven seed-or-
receive branch. The upstream owners are tighter too: `0x5962e0` is now the field-subscription
route-table opener above `[transport+0xba4]`, while `0x596530` is the `gsi_am_rating` reopen
path above `[transport+0x18bc]`. On that latter branch, `0x590dc0` is now bounded as the
state-`0` raw-endpoint seed pass over the live route handle, repeatedly pulling endpoint tuples
through `0x58bc7e` record type `0x1f3` before stamping descriptor flag byte `0x15` with `0x11`.
That makes the remaining source-flag meaning narrower too: current evidence now supports reading
byte-`0x15` bit `0x1` as a primary-endpoint-seed or endpoint-only marker. In the `gsi_am_rating`
dispatcher, clear-bit descriptors can take the richer direct transition lane, while set-bit
descriptors are staged through the queued enrichment path and still suppress that direct
transition even after the ready bit arrives.
The adjacent capacity-descriptor side is tighter too: `0x595bc0` now clearly publishes a
descriptor block from live descriptor properties `hostname`, `numwaiting`, `maxwaiting`,
`numservers`, and `numplayers` plus three carried sidecar scalars. That sidecar at
`[transport+0x1778]` is tighter now too: current evidence says it behaves as one cached pointer
into the transient work-record family at `[transport+0x1780]`, because every meaningful branch
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
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
as a seven-dword block with an owned string slot at `+0x08`, so live mode supplies a populated
payload while modes `3` and `5` deliberately enqueue an all-zero payload and reuse only
the wrapper-side sidecar metadata. Those two modes are tighter now too: they are the live
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
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
tighter too: it is a pure work-record uniqueness predicate over field `+0x0c`. Its caller is
tighter now too: `0x58d720` is an immediate-drain quiescence gate over one transport context id,
using `0x593400` for the queued work family at `[transport+0x1780]` and `0x592970` for the
active opcode-record collection at `[transport+0x17fc]`. The strongest current read is that
`0x5934c0` seeds that shared drain context id first, then the transport copies it into queued
work field `+0x0c` and active opcode-record field `+0x14` before the immediate-drain roots wait
on one shared disappearance test rather than on a vague settle loop. The currently grounded
roots are `0x58df20`, the neighboring formatted selector-text publish path at `0x58dfb0`, and
callback-table registration at `0x58e200`. The active-opcode side is tighter too: `0x5927b0`
now bounds the per-record service-and-retire path, `0x592800` the wider context-or-idle sweep,
`0x5929a0` the remove-by-opcode-type sweep, and `0x5929f0` the narrower opcode-`3`
field-snapshot removal keyed by the subscribed callback-pair payload. That also corrects
`0x595b80`, whose final cleanup is an active field-snapshot purge rather than a queued-work
drain. The adjacent route-callback descriptor-table lifecycle is tighter too: `0x590410` now
grounds `[table+0x5bc]` as the staged intrusive descriptor-list head, `0x590430` is the generic
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:
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
then forwarding `(+0x10, +0x18, +0x0c)` into `0x593170` as callback function, callback
companion, and trailing drain context. So the replay-side triplet is clearly a broader
transport callback-wrapper family, not one fixed route-only tuple. The nearby
field-subscription side is tighter too: `0x592b50` now clearly uses `[transport+0x1774]` as a
cached progress percentage under `[transport+0xba4]`, and `0x5962e0` seeds that percentage to
`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
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+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
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]`
together with target `[0xb48]` to decide whether staged route-callback traffic can push the
multiplayer route-mode ladder from `2` into `3` and later `4`. The selector-view counter beneath
that gate is tighter now too: `0x594e30` counts slot-`2` entries whose flag dword carries bit
`0x20`, optionally filtered by the current transport name buffer. The selector-view mutation
family under that same lane is tighter too: `0x594a30` is now the direct keyed-store remover,
`0x594fb0` clears one selector-slot ownership pointer plus its slot-local flag dword and drops
the whole entry when no slots remain, `0x595010` rekeys one selector-view entry under a new name
while preserving the `0x40..` runtime band, and callback root `0x59f9c0` now reads as the
sibling lane that clears one named selector-view slot, publishes callback slot `18`, and may
still re-enter the route-mode setter from the same slot-`2` status and generation gates. The
neighboring callback roots are tighter now too: `0x5950a0` clears one selector slot from every
selector-view entry in the keyed store, `0x59fab0` is the rename or relabel sibling above
`0x595010`, `0x59faf0` updates one selector slot's fixed sample-text buffer and refreshes the
active selector object when present, and `0x59fb60` replaces one selector slot's name set,
requests the default profile-key bundle for that slot, and publishes callback slot `20`. Slot
`16` is tighter now too: current grounded caller `0x59f440` forwards the staged route-callback
payload handle from `[transport+0xb50]` through `0x592ea0` just before route mode `5`. The
last adjacent callback root in that block is tighter now too: `0x59fbd0` is the built-in
per-slot profile-key query sibling. It resolves the caller selector name into one slot index,
forwards the caller trio into `0x596b90`, and then publishes callback slot `28`; that lower
helper indexes one slot-specific built-in string pair from `[transport+0x189c]` and
`[transport+0x18ac]`, reuses the generic per-key handler `0x596970`, and only republishes slot
`28` when that lower query path succeeds.
The compact-header side is tighter now too: `0x58fe20` and `0x58ff20` now show that compact
payloads always carry the primary IPv4 dword and that header bit `0x10` only gates whether the
primary port word is inline or inherited from the owner default port. `0x58fe90` now validates
the `0x40` inline keyed-property vector against the owner schema, and `0x58fe50` validates the
signed-`0x80` trailing string-pair tail before decode. `0x58ff60` then grounds bit `0x02` as
the inline secondary IPv4 dword branch, bit `0x20` as the paired secondary-port word branch with
owner-port fallback, bit `0x08` as one still-unresolved auxiliary dword stored at
`[descriptor+0x10]`, bit `0x40` as one inline keyed-property vector decoded through the
property-store writers, and signed bit `0x80` as one trailing string-pair tail. The
descriptor-state side is tighter now too: the shared queue helper at
`0x005a09a0` stamps pending state `0x4` for the local field-cache family `[transport+0x1724]`
and pending state `0x8` for the `gsi_am_rating` queued-descriptor family `[transport+0x1e7c]`,
while later service through `0x005a0c80` promotes those pending tags into ready bits `0x1` and
`0x2` in descriptor byte `[entry+0x14]`. That makes the current transport-side tests cleaner:
`0x58d1c0` is the field-cache ready gate, `0x58d1d0` is the `gsi_am_rating` queued-descriptor
ready gate, and `0x58d230` is the remaining flag-byte split between direct primary-endpoint
handling at `[transport+0x18bc]` and the queued path at `[transport+0x1e7c]`. That byte-`0x14`
story is no longer queue-only either: `0x58ff60` can also OR in bit `0x1` after the inline
keyed-property vector and bit `0x2` after the signed string-pair tail. The flag-byte split is no
longer purely behavioral either: current evidence now says byte `[descriptor+0x15]` bit `0x1` is
a source-side descriptor header bit, explicitly seeded during the primary-endpoint table refresh
around `0x590dc0` and preserved by the compact descriptor decode path at `0x58ff60`, rather than
a queue-generated runtime state. The `gsi_am_rating` dispatcher side is tighter too: that same
bit no longer just looks like a direct-versus-queued routing split, because `0x595e10` also uses
it to suppress the direct `0x595dc0` transition even after queued ready bit `0x2` is present.
The descriptor body is tighter too: `[descriptor+0x20]` is now the intrusive next-link used by
the transport-owned primary-endpoint list headed at `[table+0x5bc]`, and `[descriptor+0x1c]` is
now the special numeric scalar behind the current `queryid`/`ping` fallback pair. The compact-only
auxiliary dword at `[descriptor+0x10]` is tighter in a negative way too: local xref scans now
only show it being preserved by later generic helpers like
`generic_record_0x1c_deep_copy_with_owned_string_at_0x08` `0x591410` and the adjacent
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
`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
same service loop also owns a slower sidecar lane keyed off `[entry+0xa4]`:
`multiplayer_transport_select_stale_selector_view_progress_entry` walks the store through
`multiplayer_transport_pick_stale_selector_view_progress_entry`, picks one stale entry whose
progress latch `[entry+0x9c]` is clear and whose last progress tick `[entry+0x70]` is old enough,
and then hands it to `multiplayer_transport_stage_selector_view_progress_snapshot`. That helper
now looks more bounded too: it rebuilds the core `X%sX` marker text from `[entry+0x50]` through
`multiplayer_transport_format_selector_view_probe_marker_core`, formats one `PNG %s %d` line
around that marker and the entry-local averaged millisecond sample at `[entry+0x80]`, appends bounded
selector-slot `PNG` fragments for live overlapping slots, marks progress-snapshot state in flight
at `[entry+0x9c]`, and stamps both `[entry+0x70]` and the transport-wide throttle tick
`[transport+0xaec]`. So the selector-view sidecar no longer looks like one undifferentiated
refresh bucket: it has a faster deferred-probe lane plus a slower progress-snapshot lane, both
still under the shell-owned multiplayer transport cadence. The two descriptor lanes installed by
`multiplayer_transport_attach_callback_table_descriptor` are now tighter too. The first lane
rooted at `0x59f5c0` can arm deferred-close state on the owner transport and then forward through
callback slot `23`. The second lane is no longer just a loose selector-view bucket:
`multiplayer_transport_callback_dispatch_selector_name_payload_lane` at `0x59f650` classifies
selector payloads through `multiplayer_transport_is_selector_control_line`, routes `@@@NFO`
control lines into `multiplayer_transport_sync_selector_view_nfo_r_flag`, and otherwise publishes
either callback slot `13` or the split token-plus-tail callback slot `14` through
`multiplayer_transport_split_selector_payload_token_and_tail`. That local `@@@NFO` helper is now
bounded more tightly too: it only accepts lines ending in the literal `X\` tail, searches for the
field marker `\$flags$\`, and then sets or clears bit `0x2` in the third selector-slot flag word
at `[entry+0x64]` depending on whether that field contains the letter `r` before the next
backslash. The sibling `multiplayer_transport_callback_dispatch_current_selector_payload_lane` at
`0x59f720` first resolves the active selector through `0x5951a0`, then handles the
current-selector variants of the same control vocabulary: `@@@NFO` continues into the same local
`r`-flag sync helper, `@@@GML` plus mode-`3/4` payloads feed the shared control-token helper
`multiplayer_transport_handle_gml_or_png_selector_control`, and the remaining non-control payloads
publish callback slot `9`. That shared helper now narrows the `GML` and `PNG` split materially:
when the token is `GML` and the tail is `Disconnected`, it requires the active selector-view entry
to pass `multiplayer_transport_selector_view_entry_has_gml_disconnect_gate`, which currently means
the entry participates in the third selector slot and has bit `0x20` set in `[entry+0x64]`, before
it forces one status-pump pass, emits callback slot `16`, and re-enters route mode `5`. Its
sibling `PNG` branch resolves a named selector-view entry from the tail text and, when that entry
overlaps the active selector-slot ownership, refreshes selector-view runtime state through
`0x5948f0` and republishes callback slot `25`. Alongside those dispatchers, one grounded branch at
`0x59f560` still updates selector-view runtime state through `0x5948f0` and forwards the same
selector-name pair through callback slot `25`, while `0x59f850` resets selector text state through
`0x5954b0`, forwards through callback slot `19`, and when selector `2` is active in a nonterminal
route mode re-enters `multiplayer_transport_set_route_mode` with mode `1`. The low-level route
helper still looks like a two-part cycle:
`multiplayer_gamespy_route_service_retry_and_keepalive_timers` handles challenge or retry pressure
and periodic outbound control traffic around the `master.gamespy.com`, `PING`, `natneg`,
`localport`, `localip%d`, and `statechanged` strings, while
`multiplayer_gamespy_route_drain_inbound_packets` drains inbound datagrams and dispatches
semicolon lines, backslash-delimited key bundles, and `0xfe 0xfd` GameSpy control packets. The
transport-owned callback story is now narrower too. The shared route constructor
`multiplayer_gamespy_route_construct_and_seed_callback_vector` seeds `[route+0x88]` through
`[route+0x9c]` from the caller-supplied transport callback table, records the owner transport at
`[route+0x104]`, and explicitly zeroes `[route+0xa0]`, `[route+0xa4]`, and `[route+0xd4]` before
any later patch-up. For the transport-owned status route,
`multiplayer_transport_try_connect_status_route` then patches `[route+0xa0]` through
`multiplayer_gamespy_route_set_extended_payload_callback` to point at
`multiplayer_transport_forward_validated_extended_route_payload` `0x00597330`, which simply
forwards the validated payload wrapper into the owner callback at `[transport+0x17f4]` with
context `[transport+0x17f8]`. The grounded live-route connect path at
`multiplayer_transport_try_connect_live_route` does not currently perform any matching
post-construction patch for `[route+0xa0]`, `[route+0xa4]`, or `[route+0xd4]`, and the higher
2026-04-06 20:36:20 -07:00
route-mode state machine now looks consistent with that: `multiplayer_transport_set_route_mode`
latches the requested small mode at `[this+0x18b8]`, then uses mode `0` for the direct-versus
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
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
`[route+0xd4]` is non-null, and the subtype-`6` raw fallback only dispatches when `[route+0xa4]`
is non-null. For the currently grounded transport-owned status and live routes, those two branches
therefore remain optional and can cleanly no-op instead of implying a hidden mandatory callback
path. Inside the packet parser, subtype `4` is no longer an unknown callback hop: after cookie
validation it dispatches through `[route+0x9c]`, which the transport-owned status and live routes
seed to `multiplayer_transport_handle_validated_route_cookie_event` `0x005972c0`. That helper
either marks route progress and re-enters `multiplayer_transport_set_route_mode`, or forwards the
event id plus payload into the owner callback at `[transport+0x17f0]` with context
`[transport+0x17f8]`. The surrounding status-route callback vector is tighter now too:
`0x005970e0` publishes either the active selector text or the averaged probe sample at
`[entry+0x80]` and otherwise falls back to owner callback `[transport+0x17e0]`;
`0x00597180` is a straight owner-forwarding lane through `[transport+0x17e4]`;
`0x005971b0` seeds the local status-control id list and can then notify owner callback
`[transport+0x17e8]`; and `0x00597270` returns the third selector-slot generation counter
`[transport+0xac0]` on its bounded local branch before falling back to owner callback
`[transport+0x17ec]`. Subtype `6` still validates the same cookie, dedupes one 32-bit cookie or
packet id, and then dispatches the trailing payload through the natneg-or-raw callback layer
rooted at `[route+0xa0]` and `[route+0xa4]`. This separates the shell-frame preview refresh at
`0x006cd8d8` from the actual transport cadence at `0x006cd970`, and also separates that transport
cadence from the lower GameSpy route-service and packet-parser layer beneath it.
- Evidence: `function-map.csv`, `pending-template-store-management.md`,
`pending-template-store-functions.csv`, plus objdump caller traces showing
`multiplayer_window_service_loop` reaching `multiplayer_flush_session_event_transport` and the
transport pump chain `multiplayer_flush_session_event_transport ->
multiplayer_transport_flush_and_maybe_shutdown -> multiplayer_transport_service_frame ->
multiplayer_transport_service_worker_once -> multiplayer_transport_drain_request_text_queue`.
- Open Questions: unresolved request-id semantics for `1`, `2`, `4`, and `7`; whether any
non-mode-path helper outside the currently grounded release-and-rebuild flow ever patches
`[route+0xa4]` and `[route+0xd4]` for the transport-owned status/live routes, or whether those
packet families are simply unused in this stack; and how far the Multiplayer preview-dataset
machinery is reused outside `Multiplayer.win` beyond the currently grounded `.gmt` save-mode hook.
## Input, Save/Load, and Simulation
- Roots: the shell controller window-message ingress `shell_controller_window_message_dispatch` at
`0x0054e3a0`, the shell input-state object initialized at `0x006d4018` through
`shell_input_state_init` `0x0054e710`, the saved-world restore path
`world_load_saved_runtime_state_bundle` at `0x00446d40`, the live-world save path
`world_runtime_serialize_smp_bundle` at `0x00446240`, `world_entry_transition_and_runtime_bringup`
at `0x00443a50`, the frame-owned cadence `simulation_frame_accumulate_and_step_world` at
`0x00439140`, the recurring `GameMessage.win` service branch through
`game_message_window_service_if_present` `0x004e0720`, the world-facing `GameUppermost.win`
overlay branch ensured by `shell_ensure_game_uppermost_window` `0x004e0e40` and serviced through
`game_uppermost_window_service_world_hotspot_band` `0x004e0780`, and the lower step family rooted
at `simulation_advance_to_target_calendar_point` `0x0040ab50` with periodic branches through
`simulation_service_periodic_boundary_work` `0x0040a590`.
- Trigger/Cadence: shell-side input is event-driven by controller-window `WM_*` traffic while save
or load work is triggered either directly from shell commands or through the `fileopt.win` branch
flags into the `.smp` runtime-state family; post-bring-up world service becomes recurring once a
world root exists at `0x0062c120`, but the current grounded top-level cadence still remains the
shell-owned `shell_service_pump_iteration` path, which calls
`simulation_frame_accumulate_and_step_world` directly and lets it accumulate elapsed wall-clock
time into one or more simulation-step quanta. A second ingress is now bounded too:
`simulation_run_chunked_fast_forward_burst` at `0x00437b20` repeatedly calls the same lower
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
`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
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
`[0x006cec7c+0x87]`, materialize the per-slot chairman records from the scenario selectors,
campaign override flag `[0x006cec7c+0xc5]`, and the static persona table at `0x005f2d28`, and then
publish the selected chairman-profile and linked company summary pair through `[state+0x25]` and
`[state+0x21]`. The local slot-record shape is tighter too because the shell editor panel around
`0x004cc2d0` now surfaces it directly: `[slot+0x00]` is the staged chairman profile id,
`[slot+0x01]` is the Optional-versus-Mandatory byte with nonzero=`Optional` and zero=`Mandatory`,
`[slot+0x02]` combines with the separate per-slot gate at `[world+0x0bc3+slot*9]` to surface
`Human`, `Computer`, and `Human or Computer`, `[slot+0x03]` is the special occupied-seat byte, and
`[slot+0x04]` is the numeric tuning field. Both the selector seeder and the record materializer
treat either `[slot+0x02]` or `[slot+0x03]` as enough to keep a slot live, but current grounded
writes only seed `[slot+0x03]` on slot zero and later move it solely by whole-record compaction.
That makes `[slot+0x03]` the strongest current anchor for the distinguished primary-human-seat
flag rather than a generic role byte. The summary fields are tighter too: current direct accessors
now show `[state+0x25]` as the selected chairman profile id in `0x006ceb9c`, while `[state+0x21]`
is the linked owning company id copied from `[profile+0x1dd]` through
`scenario_state_set_selected_chairman_profile` `0x00434890`. The editor-side scenario setup
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`
`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
`map_editor_scenario_metadata_panel_handle_message` `0x004cb4a0` makes the year semantics tighter
too: it commits the description and both briefing texts from edit-control payloads, toggles the
same two booleans, and clamps the three year fields to `1829..2100` while maintaining `minimum <=
default <= maximum`, which now lines up directly with the editor strings `Description:` `Minimum
Start Year:` `Default Start Year:` `Maximum Start Year:` `Briefing` and `Multi-Player Briefing`.
The neighboring special-conditions page is clearer as well:
`map_editor_scenario_special_conditions_panel_construct` `0x004cb2b0` now grounds the live owner
for the `Setup_Options_Buttons.imb` list rooted at `0xa7fa`, walks the 36-entry static rule table
at `0x005f3ab0`, counts enabled flags from `[0x006cec78+0x4a7f]`, and publishes the `Special
Conditions In Effect` summary from localized id `1053`. The same page now has a bounded live
dispatcher too: `map_editor_scenario_special_conditions_panel_handle_message` `0x004cb8e0` handles
both bulk selection controls and direct row-state changes, commits them back into
`[0x006cec78+0x4a7f]`, and then re-enters the panel constructor to refresh the summary. That table
is no longer just a raw id run; it now clearly includes the finance and construction restrictions
`2535..2563`, plus later editor toggles such as `Use Bio-Accelerator Cars`, `Disable Cargo
Economy`, `Disable Train Crashes`, `Disable Train Crashes AND Breakdowns`, and `AI Ignore
Territories At Startup`. The neighboring available-chairman page is tighter too.
`map_editor_available_chairman_panel_construct` `0x004ca540` now bounds the shell-side owner for
the 40-entry persona-availability surface under `0x5aa0..0x5b03`: it walks the same persona table
family at `0x005f2d28`, publishes one localized chairman-name row per profile, counts enabled
availability bytes from `[0x006cec78+0x6987..]`, and emits the summary `%1 out of %2 are
selected.` from localized id `1035`. The live state owner beside it is now grounded as well:
`map_editor_available_chairman_panel_handle_message` `0x004cb6f0` handles three bulk-selection
controls `0x5aa1..0x5aa3` by rewriting that same availability-byte array from preset bytes
embedded in the persona table, and it also commits direct per-row toggle changes from
`0x5aaa..0x5b03` back into `[state+0x6987..]` before refreshing the page. So the editor lane now
has three distinct scenario-setup slices rather than one chairman-only blob: chairman slots,
scenario metadata and briefings, plus both a rule-toggle matrix and an available-chairman pool.
There is now one adjacent company-side lane too: current neighboring setup flow conditionally
enters `world_conditionally_seed_named_starting_railroad_companies` `0x0047d440` when the
Multiplayer preview owner `0x006cd8d8` is absent and either sandbox flag `[0x006cec7c+0x82]` is
set or shell-state flag `[0x006cec74+0x14c]` is set while editor-map mode `[0x006cec74+0x68]` is
clear. That helper no longer looks like a generic company refresh. It seeds exactly three fixed
named railroad-company records from `RT3.lng` ids `575..577`: `Missouri Pacific`, `New York
Central`, and `Grand Trunk Railroad`. The first seeded company is tied back to the selected
chairman-profile summary and becomes the selected company id. The second railroad is tighter now
too: it only receives a chairman link when `profile_collection_count_active_chairman_records`
finds at least two live chairman records, and the helper then binds the zero-based second active
chairman through `profile_collection_get_nth_active_chairman_record` with ordinal `1`. The third
railroad currently gets no matching chairman-link branch in the grounded setup flow and therefore
remains an unchaired named company in the live roster. The shell UI above that setup lane is now
tighter as well: `shell_company_list_window_construct` `0x004c7200` builds a live company-list
window over the company collection at `0x0062be10`, `shell_company_list_window_refresh_rows`
`0x004c6c30` formats the active companies with localized strings `267..270`, and only then
conditionally appends one synthetic row id `0x7fff` through
`shell_company_list_format_company_or_start_row` `0x004c6b40` so `<<Start New Company>>` appears
as a separate affordance rather than as part of the seeded trio itself. Current shell paging
around that same roster is tighter too because the live company collection now has a grounded
active-only ordinal helper family: `company_collection_count_active_companies` `0x00429a50`,
`company_collection_count_active_companies_before_company_id` `0x004299f0`, and
`company_collection_get_nth_active_company_id` `0x00429990`. Those helpers now anchor the “current
company among active companies” math used by shell-side detail and picker flows rather than
leaving it as anonymous collection glue. `shell_company_list_window_handle_message` `0x004c6f30`
then routes the synthetic row into `start_new_company_dialog_open` `0x0047d080`, whose commit path
now grounds through `start_new_company_dialog_commit_create_company` `0x0047d120`. That lower
helper unlinks any current chairman-owned company, allocates a fresh company id from the live
collection at `0x0062be10`, initializes it through `0x00428420`, and only then publishes the new
selected company. The neighboring compact request helper
`start_new_company_request_create_company` `0x0047d320` does the same fresh-company path from a
request block and is already reached from the startup-company branch at `0x00470e48`. The
immediate sibling shell branch below that roster is still station-oriented: current grounded
resource names and handlers put one branch on `shell_station_detail_window_construct`
`0x005068c0`, another on `shell_station_list_window_construct` `0x005074c0`, and the subordinate
selector helper on `shell_station_pick_window_construct` `0x00507620`. But the broader
company-detail ownership question is no longer open. There is now a separately grounded
`CompanyDetail.win` family rooted at `shell_company_detail_window_construct` `0x004c5540`, with
`shell_company_detail_window_handle_message` `0x004c56a0` as its main dispatcher and
`shell_company_detail_window_refresh_controls` `0x004c2ca0` as the shared repopulation pass for
the selected-company presentation and tabbed control bands around `0x9476..0x9490`. A grounded
shell detail-manager caller reaches that constructor at `0x004dde24`, the first finance-action
layer beneath it is now bounded through `shell_company_detail_issue_bond_offer_flow` `0x004c3890`,
`shell_company_detail_issue_stock_offer_flow` `0x004c3f30`,
`shell_company_detail_buyback_stock_flow` `0x004c46d0`, and
`shell_company_detail_change_dividend_rate_flow` `0x004c5360`, and the first non-finance layer is
now bounded too through `shell_company_detail_resign_chairmanship_flow` `0x004c5a0e`,
`shell_company_detail_bankruptcy_flow` `0x004c5b99`, the territory-access family rooted at
`shell_company_detail_refresh_selected_territory_access_summary` `0x004c1b60` plus
`shell_company_detail_buy_territory_access_rights_flow` `0x004c5fc9`, backed by
`company_clear_selected_chairman_if_current_profile` `0x00428a10`,
`company_declare_bankruptcy_and_halve_bond_debt` `0x00425a90`,
`company_has_territory_access_rights` `0x00424010`, `company_set_territory_access_rights_byte`
`0x00424030`, and `company_can_purchase_territory_access_rights` `0x00426be0`, plus the two
control-transfer lanes. `shell_company_detail_attempt_chairmanship_takeover_flow` `0x0050ccc0` now
grounds the special chairman's election path: it checks the caller's current stock ownership in
the target company, rejects insufficient holdings through localized id `623`, rejects recent
failed attempts through id `624`, and then opens the confirmation under id `625` before seeding
the local takeover-election state or packaging the same request through the multiplayer shell
transport. The follow-on resolver `shell_resolve_chairmanship_takeover_vote_and_commit_outcome`
`0x0050c940` now closes the single-player election loop too: it walks the active chairman profile
collection, computes weighted votes for and against the takeover, compares the affirmative total
against half the target-company value, presents the result through
`shell_present_chairmanship_takeover_vote_outcome_dialog` `0x0050c500` in single-player or
localized id `3082` in multiplayer, and then either transfers chairmanship through `0x00428a30` or
stamps the current year into `[company+0x289]` as the grounded takeover-cooldown field.
`shell_company_detail_attempt_merger_flow` `0x004ec640` now grounds the merger side too: it
rejects empty worlds through id `727`, rejects recent failed attempts through id `728`, checks the
proposed premium against company cash through localized id `3889`, and then commits into the
resolver family. That merger resolver is now bounded too:
`shell_resolve_merger_vote_and_commit_outcome` `0x004ebd10` walks the active chairman profile
collection, computes weighted votes for and against the proposed merger, compares the affirmative
total against half the target-company value, presents the result through
`shell_present_merger_vote_outcome_dialog` `0x004eb890` in single-player or localized id `3059` in
multiplayer, and then either commits the merger through `0x00427e20` or stamps the current year
into `[company+0x15f]` as the grounded merger-cooldown field. The vote-bias side beneath that
resolver is tighter now too: `scenario_state_compute_issue_opinion_multiplier` `0x00436590` is no
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
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
stat-family accessor over year-relative series or the bounded slot family in
`company_read_control_transfer_metric_slot` `0x0042a2e0`. Its recurring family token `0x2329` is
no longer treated as an issue id here either; it is the stat-family selector paired with localized
company-stat label id `2329`. That means the paired raw and scaled helpers at `0x004241e0` and
`0x00424200` now read as narrow control-transfer offer policy totals instead of direct
issue-argument consumers, and the same broader support-and-governance metric family now also feeds
the annual shareholder-revolt and creditor-liquidation lane surfaced by localized ids `300..304`.
The editor-side help text cluster around ids `2433..2437` is no longer floating either: current
grounded map-editor code now has a live economic tuning family beside the chairman-slot panel.
`map_editor_economic_cost_slider_panel_construct` `0x004cadf0` binds six slider controls through
`map_editor_economic_cost_slider_dispatch` `0x004ca980` into the scenario-state float block
`[0x006cec78+0x0be2..0x0bf6]`, while the surrounding descriptor table at `0x00611c70..0x00612220`
pairs that wider editor lane with localized fields `Prime Rate`, `Merger Premium`, and `Build
Stations Cost` through `Steam Engine Cost` plus the comparison or help texts `2433..2437`. The
broader shell-state master flag at `[0x006cec74+0x68]` still sits above the remaining post-load
phases, plus two narrower per-phase gates: `[0x006cec74+0x174]` directly fronts id `320` `Setting
Up Buildings...` and the later region-owned structure-demand and placement pass through
`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
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
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`
`0x00437a60`.
- CompanyDetail addendum: the shared helper `shell_company_detail_resolve_selected_company` at
`0x004c16f0` now bounds the common current-company accessor beneath the whole pane, and the
read-side owner also has a separate active-company navigation family through
`shell_company_detail_step_selected_active_company_delta` at `0x004c3470` plus the next or
previous wrappers at `0x004c3540` and `0x004c3550`. The section switch in
`shell_company_detail_window_refresh_controls` is now grounded too: section index `0x006cfe60`
selects a chairman/governance slice, a debt-and-capital slice, a per-share slice, or a
territory-access slice, published through the tab band around `0x9472..0x9479`, with adjacent
section-navigation controls around `0x947b..0x947c` and `0x948f..0x9490`.
- Key Dispatchers: `shell_controller_window_message_dispatch`,
`shell_input_apply_window_key_transition`, `shell_input_snapshot_dispatch_state`,
`shell_input_cursor_inside_active_view`, `world_load_saved_runtime_state_bundle`,
`world_runtime_serialize_smp_bundle`, `simulation_frame_accumulate_and_step_world`,
`game_message_window_service_if_present`, `game_message_window_service_frame`,
`game_uppermost_window_handle_message`, `game_uppermost_window_service_world_hotspot_band`,
`game_uppermost_window_refresh_controls`,
`world_view_service_keyboard_turn_pan_and_zoom_bindings`, `world_view_step_heading_quadrant`,
`world_view_step_zoom_bucket`, `world_seed_default_chairman_profile_slots`,
`world_build_chairman_profile_slot_records`,
`world_conditionally_seed_named_starting_railroad_companies`,
`scenario_state_set_selected_chairman_profile`,
`scenario_state_get_selected_chairman_profile_record`,
`scenario_state_get_selected_chairman_company_record`, `shell_company_list_window_construct`,
`shell_company_list_window_refresh_rows`, `shell_company_list_window_handle_message`,
`start_new_company_dialog_open`, `start_new_company_dialog_commit_create_company`,
`start_new_company_request_create_company`, `shell_station_detail_window_construct`,
`shell_station_list_window_construct`, `shell_station_list_window_handle_message`,
`shell_station_pick_window_construct`, `shell_station_pick_window_populate_station_rows`,
`map_editor_chairman_slot_panel_construct`, `map_editor_chairman_slot_panel_handle_message`,
`map_editor_chairman_slot_panel_refresh_selected_slot`,
`map_editor_chairman_slot_panel_cycle_selected_slot_profile`,
`map_editor_available_chairman_panel_construct`,
`map_editor_available_chairman_panel_handle_message`,
`map_editor_scenario_metadata_panel_refresh_briefing_mode`,
`map_editor_scenario_metadata_panel_refresh_controls`,
`map_editor_scenario_metadata_panel_handle_message`,
`map_editor_scenario_special_conditions_panel_construct`,
`map_editor_scenario_special_conditions_panel_handle_message`,
`map_editor_economic_cost_slider_panel_construct`, `map_editor_economic_cost_slider_dispatch`,
`station_place_world_surface_sync_and_dispatch`, `station_place_window_handle_message`,
`track_lay_window_refresh_controls`, `track_lay_window_service_frame`,
`track_lay_window_handle_message`, `simulation_advance_to_target_calendar_point`, the smaller
single-step helper at `0x00409e80`, `0x0040a9c0`, `0x0040a910`, and
`simulation_service_periodic_boundary_work`.
- State Anchors: shell input object `0x006d4018`, per-key state table starting at `[input+0x100]`,
packed shell input flags at `[input+0xa8c]` now grounded as Right Shift `0x1`, Left Shift `0x2`,
Control `0x4`, and Alt `0x20`, nested dispatch counter `[input+0xa90]`, global shell controller
`0x006d4024`, active world root `0x0062c120`, `GameMessage.win` object `0x006d081c`,
`GameUppermost.win` overlay object `0x006d0820`, `StationPlace.win` tool object `0x006d1720`,
`TrackLay.win` tool object `0x006d1a8c`, accumulated leftover simulation time at `[this+0x4c80]`,
shell and mode globals at `0x006cec74`, `0x006cec78`, and `0x006cec7c`, world manager collections
at `0x0062be10`, `0x006ceb9c`, `0x006cfcbc`, `0x006cec20`, `0x0062bae0`, and `0x006acd34`, plus
the packed calendar-like tuple fields around `[this+0x0d]`, `[this+0x0f]`, `[this+0x11]`, and
`[this+0x14]`.
- Subsystem Handoffs: the controller window dispatcher now looks like the first grounded input
ingress. It translates keyboard and mouse `WM_*` traffic into shell controller state and the
separate input object at `0x006d4018`; read-side cursor and camera helpers later snapshot that
object through `shell_input_snapshot_dispatch_state` and gate world-relative interaction through
`shell_input_cursor_inside_active_view`. Current grounded consumers around `0x00478cb0`,
`0x004e0780`, `0x0053f450`, and `0x0053fe90` still sit on the shell controller path and consult
`0x006d4024` or the world owner at `0x0062be68`, so there is still no evidence for a distinct
gameplay-only input object after world entry. Instead, the first deeper world-mode interaction
branch now looks like a shared world-view coordinator layered on top of the same shell-fed input
state. Shell_transition_mode ensures the `GameUppermost.win` object at `0x006d0820`; its message
dispatcher `game_uppermost_window_handle_message` owns the narrow action band `0x7918` through
`0x7921`; and the recurring service helper `game_uppermost_window_service_world_hotspot_band`
rate-limits those hotspot actions, rechecks `shell_input_cursor_inside_active_view`, and then pans
the live world view through `world_view_pan_relative_offset_in_camera_plane` `0x0043d130`. The
same lower setter family is also reached from the cursor-drag path through
`world_view_apply_screen_delta_to_focus_position` `0x0043d0c0`. Above both of those sits the
larger recurring service `world_view_service_shell_input_pan_and_hover` `0x0043db00`, which now
has one grounded keyboard branch beneath it:
`world_view_service_keyboard_turn_pan_and_zoom_bindings` `0x0043d740`. That helper resolves four
binding-pair families from the shell input table via `0x0054e7d0`, and the localized labels are
now grounded from `Data/Language/RT3.lng`: `Camera Forward` and `Camera Backward` feed the first
signed pan channel, `Camera Left` and `Camera Right` feed the second signed pan channel, `Camera
Zoom In` and `Camera Zoom Out` feed the signed zoom-step channel that `0x0043db00` smooths into
`world_view_step_zoom_bucket` `0x0043cc30`, and `Camera Rotate Left` plus `Camera Rotate Right`
feed the continuous heading-turn branch through `0x0043c810`. The setup side is now better bounded
too: `world_view_seed_keyboard_binding_slot_pairs` at `0x00439e40` seeds the eight slot pairs at
`[this+0x0a6]` through `[this+0x0e2]` from the global action-binding registry through `0x0045f370`
using the distinct registry keys `0x0043d2a0` through `0x0043d310`, and the registration block at
`0x00460769` through `0x004608e7` shows those roots are defaulted to the expected Up Down Left and
Right virtual keys before runtime polling begins. Beneath that camera stack, the enclosing frame
path now has one grounded non-view sidecar: after `0x0043db00` it reads the active controller-view
object pointer at `[0x006d4024+0x18]+0x366e`, compares it against the latched target at
`[frame_owner+0x66a2]`, fires exit and enter-style vtable callbacks on pointer changes through
slots `+0x64` and `+0x60`, and only latches the new object when the object passes its own slot
`+0x1c` availability test and shell detail control id `0x07d6` on `0x006d0818` has flag bit `0x4`.
That `0x07d6` gate is now more bounded than before: the dedicated `TrackLay.win` tool family
rooted at `0x006d1a8c` special-cases the same control id in both `track_lay_window_service_frame`
and `track_lay_window_handle_message`, uses world hit tests through `0x00448ac0` to arm and
release a drag latch on that surface, and routes the resulting command work through the shared
track-lay mode state at `0x00622b0c`. The surrounding `track_lay_window_refresh_controls` pass now
shows that this is not just one isolated drag handler: the same tool family owns three mutually
exclusive primary mode buttons at `0x985e` `0x985f` and `0x9860`, and current primary evidence now
bounds those values as `Lay single track.` `0x1`, `Lay double track.` `0x4`, and `Bulldoze` `0x40`
from the localized strings 2054 2055 and 1721 plus the matching control-routing branches in
`track_lay_window_handle_message`. The same family also owns the downstream route-entry policy
bridge at `0x004955b0`: current caller evidence says that helper maps the live TrackLay primary
mode into endpoint-synthesis policy `1` or `4` before the tool re-enters `0x00493cf0`, which is
the strongest current bridge from the player-facing single-track versus double-track buttons into
the lower route-builder policy bytes. The same family also owns a bridge-type preference selector
rooted at `0x006cec74+0x138`, two wrapped `Never` through `Common` frequency settings at
`0x006cec74+0x140` and `0x006cec74+0x13c`, two boolean track-lay preference toggles, and the
electrify-all-track action path. Those last two toggles are now tighter than before: current
evidence strongly aligns control `0x986e` and state `0x006cec74+0x144` with `Auto-Hide Trees
During Track Lay` from strings 1838 and 1839, while control `0x986d` and state `0x006cec78+0x4c74`
align with `Auto-Show Grade During Track Lay` from strings 3904 and 3905. That mapping is still
evidence-backed rather than absolutely direct from a recovered resource table, but the state
ownership and control order now make it the strongest current fit. That makes `0x07d6` look like
the shared main-world interaction surface inside a broader TrackLay world-command subsystem, not
an unrelated detail button. The neighboring `StationPlace.win` family is now grounded on that same
surface too: the shell detail-panel constructor family allocates it through
`station_place_window_construct` at `0x00509d80`, publishes it at `0x006d1720`, services it each
frame through `station_place_window_service_frame` at `0x0050a530`, and routes player-facing
commands through `station_place_window_handle_message` at `0x005091b0`. That dispatcher
special-cases the same `0x07d6` control, and the shared helper
`station_place_world_surface_sync_and_dispatch` at `0x00508bb0` either accepts that direct surface
traffic or falls back to the same detail-panel control looked up through `0x006d0818`, rechecks
flag bit `0x4`, hit-tests the world through `0x00448ac0`, stages world coordinates into
`0x006d1738` and `0x006d173c`, refreshes the selected-site summary through
`station_place_format_selected_site_summary`, and updates the live station-placement selection
state at `0x00622af0`, `0x00622aec`, and `0x006d1740`. Together with
`station_place_select_category_and_refresh` `0x00508880`,
`station_place_refresh_category_controls` `0x00507b90`, and `station_place_format_preview_panel`
`0x00508730`, that makes StationPlace a second grounded consumer of the shared main-world
interaction surface rather than only a sibling constructor plus frame hook. The StationPlace
control semantics are now tighter too: the top category strip at `0x697c` through `0x6981` now
grounds as small station, medium station, large station, service tower, maintenance facility, and
non-station building from `RT3.lng` strings 2197 through 2202. For the three station categories
only, the secondary strip at `0x6988` and `0x6989` plus display field `0x698c` no longer looks
like another placement mode family; it is a building-style scroller. The click handlers on
`0x6988` and `0x6989` cycle the style override in `0x00622aec`, and the display path builds the
active style token from `StationSml`, `StationMed`, or `StationLrg` plus the localized
architecture styles `Victorian`, `Tudor`, `Southwest`, `Persian`, `Kyoto`, and `Clapboard` from
`RT3.lng` ids 2672 through 2667. One layer lower, the remaining opaque controls are now much
tighter: `0x6985` and `0x6986` are no longer a generic assist toggle but the two station-rotation
policy choices from strings 2207 and 2206, switching between auto-orienting the building to track
or obstacles and strictly obeying the rotation specified by the circle above. The dedicated
control at `0x6987` is the station-rotation circle itself, wired through callback `0x00507a90` and
aligned with `Click to rotate the building. You can also use bracket keys [ and ] to rotate
buildings.` string 2208. That matches the lower behavior too: when the strict-rotation choice is
off, both preview and commit paths route staged coordinates through `0x00508040`, which performs
the extra orientation search before validation; when strict rotation is on, that pass is skipped
and the current angle in `0x006d172c` is used directly. The direct shell UI also exposes the same
discrete view-step family through `world_view_step_heading_quadrant` `0x0043cb00` and
`world_view_step_zoom_bucket` `0x0043cc30`. The neighboring gating predicates
`world_view_should_drive_primary_pan_channel` and `world_view_should_drive_secondary_pan_channel`
test packed shell input bits `0x3`, and `shell_input_apply_window_key_transition` now grounds
those bits as the left and right Shift modifiers from scan codes `0x2a` and `0x36`. That means
cursor drag, overlay hotspots, held Shift state, direct keyboard turn/pan/zoom bindings, the
TrackLay and StationPlace world-command surfaces, and at least one frame-owned hover or
focus-target branch all converge under the same shell-fed world-mode input path rather than a
separate gameplay-input stack.
- Evidence: function-map rows for `shell_controller_window_message_dispatch`,
`shell_drain_pending_window_messages`, `shell_input_state_init`,
`shell_input_apply_window_key_transition`, `shell_input_snapshot_dispatch_state`,
`shell_input_cursor_inside_active_view`, `world_load_saved_runtime_state_bundle`,
`world_runtime_serialize_smp_bundle`, `world_entry_transition_and_runtime_bringup`,
`simulation_frame_accumulate_and_step_world`, `game_message_window_service_if_present`,
`game_message_window_service_frame`, `shell_ensure_game_uppermost_window`,
`game_uppermost_window_construct`, `game_uppermost_window_handle_message`,
`game_uppermost_window_service_world_hotspot_band`, `world_view_set_focus_position_xyz`,
`world_view_apply_screen_delta_to_focus_position`,
`world_view_pan_relative_offset_in_camera_plane`, `world_view_seed_keyboard_binding_slot_pairs`,
`world_view_service_keyboard_turn_pan_and_zoom_bindings`, `world_view_step_heading_quadrant`,
`world_view_step_zoom_bucket`, `world_view_should_drive_primary_pan_channel`,
`world_view_should_drive_secondary_pan_channel`, `world_view_service_shell_input_pan_and_hover`,
`world_seed_default_chairman_profile_slots`, `world_build_chairman_profile_slot_records`,
`world_conditionally_seed_named_starting_railroad_companies`,
`profile_collection_count_active_chairman_records`,
`profile_collection_get_nth_active_chairman_record`,
`scenario_state_set_selected_chairman_profile`,
`scenario_state_get_selected_chairman_profile_record`,
`scenario_state_get_selected_chairman_company_record`, `start_new_company_dialog_open`,
`start_new_company_dialog_commit_create_company`, `start_new_company_request_create_company`,
`shell_company_list_format_company_or_start_row`,
`shell_company_list_activate_or_shift_center_company`, `shell_company_list_window_refresh_rows`,
`shell_company_list_window_handle_message`, `shell_company_list_window_construct`,
`shell_company_detail_window_refresh_controls`, `shell_company_detail_window_construct`,
`shell_company_detail_window_handle_message`, `shell_station_detail_window_construct`,
`shell_station_list_window_construct`, `shell_station_list_window_handle_message`,
`shell_station_pick_window_construct`, `shell_station_pick_window_populate_station_rows`,
`map_editor_chairman_slot_panel_construct`, `map_editor_chairman_slot_panel_refresh_slot_list`,
`map_editor_chairman_slot_panel_refresh_selected_slot`,
`map_editor_chairman_slot_panel_refresh_slot_counters`,
`map_editor_chairman_slot_panel_cycle_selected_slot_profile`,
`map_editor_chairman_slot_panel_handle_message`, `map_editor_available_chairman_panel_construct`,
`map_editor_available_chairman_panel_handle_message`,
`map_editor_scenario_metadata_panel_refresh_briefing_mode`,
`map_editor_scenario_metadata_panel_refresh_controls`,
`map_editor_scenario_metadata_panel_handle_message`,
`map_editor_scenario_special_conditions_panel_construct`,
`map_editor_scenario_special_conditions_panel_handle_message`,
`map_editor_economic_cost_slider_panel_construct`, `map_editor_economic_cost_slider_dispatch`,
`station_place_refresh_category_controls`, `station_place_format_selected_site_summary`,
`station_place_format_preview_panel`, `station_place_select_category_and_refresh`,
`station_place_world_surface_sync_and_dispatch`, `station_place_window_handle_message`,
`station_place_window_construct`, `station_place_window_service_frame`,
`track_lay_window_refresh_controls`, `track_lay_window_construct`,
`track_lay_window_service_frame`, `track_lay_window_handle_message`, and
`simulation_service_periodic_boundary_work`, plus the shell-input disassembly around `0x0054f290`,
the world-view setup and service branches around `0x00439e40`, `0x0043d740`, `0x0043db00`,
`0x0043cb00`, and `0x0043cc30`, the `319` setup-side branches around `0x004377a0`, `0x00437220`,
`0x00477820`, `0x00477860`, `0x0047d440`, `0x004c6c30`, `0x004c6f30`, `0x0047d080`, `0x0047d120`,
`0x0047d320`, `0x004c2ca0`, `0x004c5540`, `0x004c56a0`, `0x005068c0`, `0x005071e0`, `0x005074c0`,
and `0x005076c0`, the direct summary-field helpers around `0x00434870` `0x00434890` and
`0x004348c0`, the company-link writers at `0x00427c70` and `0x00427d74`, the company constructor
at `0x00428420`, the startup-company branch around `0x00470e48`, the shell company-list strings
`266` `<<Start New Company>>`, `267` `You are the chairman of the %1!`, `268` `The %1 has no
chairman at the moment.`, `269` `%1 is the chairman of the %2.`, `270` `Double-click for
details.`, and `2992` `Shift-Click to center on this company's primary station.`, the
`CompanyDetail.imb` and `CompanyDetail.win` resource strings in `.rdata`, the `StationDetail.imb`,
`StationDetail.win`, `StationList.win`, and `StationPick.win` resource strings in `.rdata`, the
shell editor window branches around `0x004c9da0`, `0x004ca010`, `0x004ca1c0`, `0x004ca540`,
`0x004ca670`, `0x004ca790`, `0x004ca980`, `0x004cb2b0`, `0x004cb4a0`, `0x004cb6f0`, `0x004cb8e0`,
`0x004cc250`, `0x004cc2d0`, `0x004ceb90`, and `0x004cecc0`, the localized chairman-slot strings
`2997` through `3001` `Optional` `Mandatory` `Human or Computer` `Computer` and `Human`, the
localized scenario-editor strings `1483..1492` `Description:` through `Type the briefing for this
map.`, the localized summary strings `1035` `%1 out of %2 are selected.` and `1053` `Special
Conditions In Effect`, the 40-entry persona availability page under `0x5aa0..0x5b03`, the 36-entry
special-condition table at `0x005f3ab0` covering ids `2535..2563`, `2874`, `3722`, `3835`, `3850`,
`3852`, and `3920`, the static persona table at `0x005f2d28`, the selector array at
`0x006cec7c+0x87`, the persona collection at `0x006ceb9c`, the localized persona strings in
`Data/Language/RT3.lng` including `2730` `Unassigned`, the named-chairman range `2731+`, and the
neighboring biography range `2495+`, plus the seeded railroad-name strings `575` `Missouri
Pacific`, `576` `New York Central`, and `577` `Grand Trunk Railroad`, the StationPlace.win
constructor plus category, dispatcher, rotation-circle, shared-world-surface, preview-build, and
recurring service branches around `0x00507a90`, `0x00507b90`, `0x00508550`, `0x00508730`,
`0x00508880`, `0x00508bb0`, `0x005091b0`, `0x00509d80`, and `0x0050a530`, the StationPlace string
cluster `Place a small station` 2197 `Place a medium station` 2198 `Place a large station` 2199
`Place a service tower` 2200 `Place a maintenance facility` 2201 `Place a non-station building`
2202 `Scroll through building styles.` 2203 `When placing the building, it will strictly adhere to
the rotation specified by the circle above.` 2206 `When placing the building, it will rotate
itself as needed to orient to track or avoid obstacles.` 2207 `Click to rotate the building. You
can also use bracket keys [ and ] to rotate buildings.` 2208 and the architecture-style labels
`Clapboard` 2667 `Kyoto` 2668 `Persian` 2669 `Southwest` 2670 `Tudor` 2671 and `Victorian` 2672,
the TrackLay.win constructor and dispatcher family around `0x0050d2d0`, `0x0050e400`,
`0x0050e1e0`, and `0x0050e5c0`, the localized `Never` through `Common` strings 615 through 618,
the track-lay strings `Bulldoze` 1721 `Lay single track.` 2054 `Lay double track.` 2055 and 3114,
the TrackLay preference strings `Auto-Hide Trees During Track Lay` 1838 `If 'Auto-Hide Trees
During Track Lay' is checked, trees will automatically be reduced to small stumps whenever you are
in track laying mode.` 1839 `Auto-Show Grade During Track Lay` 3904 and `If 'Auto-Show Grade
During Track Lay' is checked, you'll see the grade number over the track while laying track -
useful for trying to keep your slopes to a minimum.` 3905, the electrify-all confirmation and
failure strings 3083 3084 3837 and 3900, the binding-registry lookup path at `0x0045f370`, the
registration block at `0x00460769` through `0x004608e7`, and the localized labels in
`Data/Language/RT3.lng` ids `3466` through `3473`.
- Open Questions: no separate outer gameplay loop is grounded above
`simulation_frame_accumulate_and_step_world` yet and no deeper gameplay-only input object is
grounded either. The new setup-pipeline evidence narrows that question in one direction: the
currently grounded chunked burst path at `0x00437b20` now looks subordinate to
`world_run_post_load_generation_pipeline` rather than to the ordinary speed controls, and even
there it still reuses the same lower stepper and pumps shell work between chunks instead of
revealing a detached gameplay loop owner. The player-facing speed-control family is now cleaner
too: `world_set_game_speed_mode` owns the bounded `Paused` through `Very Fast` ladder plus the
hidden `Ultra Fast 6..9` extension, `world_toggle_pause_or_restore_game_speed` uses `[this+0x1d]`
as the resume slot, and the multiplayer host restriction now looks attached to that same setter
family rather than to the setup-side burst helper. The frame-owned shell coupling is tighter now
too: inside `simulation_frame_accumulate_and_step_world` itself, one direct branch opens or
focuses `LoadScreen.win` through `shell_open_or_focus_load_screen_page`, and the post-step
shell-window ladder also probes several sibling shell windows by the same presence-plus-dirty
pattern, including the live `LoadScreen` singleton, the shared callback-driven custom modal, the
shared file-options dialog, `SettingsWindow.win`, the now-grounded `Overview.win` and
`BuildingDetail.win` singletons, and now the shell-side `Trainbuy.win` singleton too. That
train-buy family is no longer just an unnamed probe pair either: the opener path is now grounded
under the same shell-owned cadence through `shell_can_open_trainbuy_window_or_warn` and
`shell_open_or_focus_trainbuy_window`, and its current family semantics already extend beyond a
bare locomotive picker into selected-train upgrade summary and route-edit affordances. The
selected-train side is tighter now too: we have explicit query helpers for the selected train
record, id, validity, and company ownership, plus one explicit ownership-mismatch warning modal.
That same pass also clarified one boundary we should not conflate: the neighboring shell family
rooted at `0x006d3b20` is now grounded separately as `TrainDetail.win`. It reuses the same
selected-train context and some of the same helpers, but it is not the same `Trainbuy.win`
singleton family. The `TrainDetail.win` side now has its own constructor, opener, refresh path,
and message owner above the broader train-command strip. Its inner `0xcb` strip is tighter now
too: one bounded branch is the selected-train engine-replacement or trainbuy handoff lane using
warning ids `593/594`, and another is the selected-train retirement lane using `595/596/597`
with either a local teardown path or multiplayer opcode `0x37`. The remaining train-command
family is narrower too: the shared `0x33`-stride helper trio at `0x004b2f00`, `0x004b3000`, and
`0x004b3160` now looks like a real train route-stop or waypoint list rather than a generic row
buffer, and route-entry flag byte `+0x28` now has one grounded top-level split: sign bit clear
entries are the live placed-structure-backed family, while sign bit set entries use the direct
route-node payload side. The helper `train_route_list_count_live_site_reference_entries`
`0x004b2b80` now counts the first family explicitly. One deeper lower-bit result is grounded too:
both `train_route_list_insert_staged_entry_at_index` and the auxiliary finalize helper
`train_finalize_aux_route_entry_buffer_preserving_subflags` `0x004a94b0` explicitly preserve
bits `0x40`, `0x20`, and `0x10` in the same flag byte during route-entry rewrites. Those bits are
also no longer copy-only: the neighboring shell helper
`shell_building_detail_refresh_flagged_service_capability_rows` `0x004b9a20` now consumes them to
restyle the `BuildingDetail.win` row bands `0x7d07..0x7d1c` and `0x7f58..0x801f`. The exact
player-facing labels for those rows are still open, but the subflags now have one real shell-side
consumer instead of only preservation logic. The broader `BuildingDetail.win` refresh family is
tighter too: `shell_building_detail_refresh_subject_cargo_and_service_rows` `0x004ba3d0` now
clearly owns the selected subject rows around `0x7d06`, `0x7d96..`, and `0x7d0e`, resolving
ordinary ids through the live candidate collection and the special express-side ids through the
embedded `AnyCargo.imb`, `AnyFreight.imb`, and `PassMail.imb` paths. The first fixed triplet is
now table-grounded instead of only inferred: `0x00621df8` seeds the short-label controls
`0x7dc8..0x7dca` with RT3.lng `494..496` `Any Cargo`, `Any Freight`, and `Any Express`, while
`0x00621e10` seeds the adjacent `0x7e90..0x7e92` icon-name triplet with `AnyCargo`,
`AnyFreight`, and `PassMail` before `%1.imb` formatting. RT3.lng also tightens the longer popup
side now: `0x00621e04` feeds the first clickable selector triplet `0x7f58..0x7f5a` with
`494/497/498`, so the help text there is `Any Cargo`, `Any Freight\n(Freight is everything but
Passengers, Mail, and Troops)`, and `Any Express\n(Express is Passengers, Mail, and Troops)`.
The sibling special service rows still align to `Dining Car` and `Caboose`. The extracted
`BuildingDetail.win` blob now sharpens the resource boundary too: its embedded text table is
currently sparse rather than rich, exposing the help line for `0x7d01`, repeated
`BuildingDetail.imb` asset strings, and one standalone caption entry `Cargo`. That makes
`Cargo` the strongest current resource-side anchor for the row header around `0x7d06`. The
ordinary deeper rows are tighter now too: they do not look like hidden caption-table entries,
but like live candidate-derived rows. The current path validates each ordinary id through
`indexed_collection_entry_id_is_live` `0x00517d40`, resolves the concrete candidate record
through `indexed_collection_resolve_live_entry_by_id` `0x00518140`, and then reuses candidate
field `[record+0x04]` as one shared stem for both the row asset `%s.imb` path and the
neighboring display-label lookup through
`localization_lookup_display_label_by_stem_or_fallback` `0x0051c920`. That lookup is now
bounded too: it scans the static stem table at `0x006243c8`, already grounding entries such as
`Alcohol`, `Aluminum Mill`, `Automobiles`, `Bauxite`, and `Big Boy` against RT3.lng
`3202..3220`, and only falls back to localized id `3866` when no table entry matches before the
fixed `0x384..0x386` express-side triplet takes over. One neighboring candidate-side helper is
tighter now too: `structure_candidate_query_route_style_or_local_availability_metric`
`0x0041e650` shares the same route-style byte at `[candidate+0x46]`, returning the cached local
float at `[candidate+0x5a]` for ordinary candidates but switching route-style rows to one
normalized count over the world-side route-link collection `0x006ada90` keyed by candidate class
`[candidate+0x3e]`. That collection is tighter now too: it is constructed during world bring-up
by `placed_structure_route_link_collection_construct` `0x00468110`, and current grounded
creation flow through `placed_structure_route_link_allocate_site_pair_for_candidate_class`
`0x00467f50` seeds class byte `+0x10`, a masked initial state template, and the strongest
current creation-side site-pair fields at `+0x0c` and `+0x0e` before
`placed_structure_route_link_attach_site_owner` `0x00467eb0` links the new route-link record
into the placed-structure-owned chain at `[site+0x272]`. The owner-side split is tighter now
too: route-link field `+0x08` is the separate route-node-style owner anchor used by
`placed_structure_route_link_attach_route_node_owner` `0x00467f20`, while `+0x0a/+0x0c/+0x0e`
now read as the site-reference triple matched by
`placed_structure_route_link_collection_remove_links_touching_site_id` `0x004681f0`. Creation
flow now sharpens that further: `+0x0c` is the strongest current candidate for the stable
first-site field seeded before owner attachment, `+0x0a` is the mutable owner-site anchor
installed by the attach helper, and `+0x0e` is the stable second-site field. One more split is
tighter now too: `placed_structure_route_link_recompute_endpoint_pair_state` `0x00467c30`
currently uses `+0x0a` and `+0x0e` as the active endpoint site pair while recomputing state
byte `+0x12`; `+0x0c` is still not directly read there. The family also has a clearer release
and refresh side now: `placed_structure_route_link_release_and_detach` `0x004680b0` rolls back
the class counters and then tails into `placed_structure_route_link_detach_current_owner_chain`
`0x00467df0`, while
`placed_structure_route_link_collection_recompute_all_endpoint_pair_state` `0x004682c0`
explicitly reruns the per-record endpoint-pair reconciler across the whole live route-link
collection. One layer above that,
`placed_structure_route_link_rebuild_route_style_grid_counters_and_endpoint_state`
`0x00468300` now looks like the full-family refresh owner: it clears three route-style class
lanes in the world-grid tables rooted at `[0x0062c120+0x2129]`, then clears bit `0x2` across
the live route-link records and reruns the endpoint-pair reconciler. That now lines up with the
visible shell split: non-route candidates keep the richer local metric and price lane, while
route-style candidates use one world-side route-link family instead. The emission side is
tighter now too: `placed_structure_try_emit_best_route_style_peer_link_for_candidate_class`
`0x0040fef0` scans the live placed-structure collection for one best peer site by
class-specific weight, distance window, and type gate, then only creates a new route-link
through `placed_structure_route_link_allocate_site_pair_for_candidate_class` `0x00467f50` when
`placed_structure_endpoint_pair_has_shared_route_entry_key` `0x0040fbe0` says the chosen site
pair does not already share a route-entry key. One layer above that,
`placed_structure_rebuild_route_style_candidate_scores_and_peer_links` `0x004101e0` now reads
as the broader per-site owner of this lane: it computes per-class route-style score scalars from
local site state and scenario multipliers, drives the first three route-style emission attempts,
and then continues into a larger descriptor-driven scoring phase. Inside that larger pass,
`placed_structure_accumulate_candidate_metric_or_emit_route_style_peer_link` `0x0042cab0`
now cleanly shows the split between ordinary candidates, which add directly into the local
route-style grid lane at `[site+candidate*4+0x103]`, and remapped route-style candidates, which
re-enter the peer-link emitter. One layer above that, the broader post-create or post-edit site
rebuild `placed_structure_finalize_creation_or_rebuild_local_runtime_state` `0x0040ef10`
conditionally re-enters `0x004101e0` with stack flag `1` when its local latch at `[site+0x29e]`
stays clear, so the route-style lane is no longer floating under an unnamed single-site caller.
The placement side is tighter now too: the direct constructor
`placed_structure_collection_allocate_and_construct_entry` `0x004134d0` is the shared allocator
immediately beneath the current placement-side callers before they hand the new site into
`0x0040ef10`, and the lower constructor
`placed_structure_construct_entry_from_candidate_and_world_args` `0x0040f6d0` now bounds the
actual field-seeding layer beneath that allocator. The old unresolved higher placement chooser is
bounded more cleanly now too: the `0x00403ed5` and `0x0040446b` direct-placement commits sit
inside one larger helper,
`city_connection_try_build_route_with_optional_direct_site_placement` `0x00402cb0`. That shared
heavy builder is now the common target of the compact wrapper `0x00404640`, the peer-route
candidate builder `0x004046a0`, the region-entry pair wrapper
`city_connection_try_build_route_between_region_entry_pair` `0x00404c60`, and the direct retry
paths inside `simulation_try_select_and_publish_company_start_or_city_connection_news`
`0x00404ce0`. Internally it now has three bounded lanes:
an early route-entry search or synthesis attempt through
`route_entry_collection_try_build_path_between_optional_endpoint_entries` `0x004a01a0`,
a single-endpoint direct-placement lane that scans `Maintenance` and `ServiceTower` candidates
and commits through `0x00403ed5 -> 0x004134d0 -> 0x0040ef10`,
and a later paired-endpoint fallback lane that seeds two endpoint candidates from the same stem
family, walks a temporary route-entry list, and commits through
`0x0040446b -> 0x004134d0 -> 0x0040ef10`.
That early lane can now be described more concretely: it can reuse supplied route-entry
endpoints, synthesize a missing leading endpoint from the caller's coordinates, seed the
route-store builder-state block, and then hand off to the deeper path-search core without
placing a new site. The previously vague side family at `0x006cfcb4` is tighter too: current
evidence now bounds it as a small auxiliary route-entry tracker collection with an allocator at
`0x004a42b0`, a refcount or destroy path at `0x004a4340`, a direct route-entry group-id setter
at `0x00489f80`, an endpoint-membership probe at `0x00494ed0`, a boolean-latch refresh or
owner-notify path at `0x00494fb0`, and a two-endpoint merge or bind helper at `0x00494f00`.
That bind side is tighter now too: the trackers group route entries only when a route-key-like
value from `0x0048aa70`, the route-entry signature word `+0x22e`, and the boolean latch derived
from byte `+0x44` all agree. The deeper handoff under that lane is no longer anonymous either:
`route_entry_collection_search_path_between_entry_or_coord_endpoints` `0x0049d380` is now
bounded as the internal search core that runs the first candidate sweep, quality gates, and the
later route-extension fallbacks before returning one resolved route-entry id or `-1`. The first
sweep now has a bounded owner at `0x0049bd40`, and the two later fallback helpers are bounded as
the route-entry point-window coverage query `0x00494cb0` and the frontier-extension helper
`0x0049c900`. The math side is bounded more cleanly now too: the family reuses
`math_measure_float_xy_pair_distance` `0x0051db80` for its direct point-to-point scalar,
`math_compute_quadrant_adjusted_heading_angle_from_xy_pair` `0x004952f0` for heading-angle
construction, `math_normalize_subtracted_angle_delta_and_report_wrap` `0x004953c0` for wrapped
angle-delta checks, and `math_abs_double_with_crt_special_case_handling` `0x005a152e` for the
absolute-value side of the quality gates. Current evidence also bounds the threshold shape a
little more tightly: the initial sweep and later extension path both reuse one signed angle-bias
term `+/-0.181000038854627`, and the first sweep switches between a looser `1.4` and stricter
`1.8` quality multiplier depending on route-policy byte `4` or the broader display-runtime
preference `[0x006cec78+0x4c74]`, already grounded elsewhere as `Auto-Show Grade During Track
Lay`.
The small policy-byte semantics are still not fully closed, but current evidence is tighter than
before. Literal byte `1` is now the strongest current match for direct linked-site
endpoint-anchor creation or replacement, because the linked-site constructor and neighboring
repair branches around `0x00480463`, `0x00480a77`, and `0x00480b69` all feed that byte into
`0x00493cf0` before rebinding one chosen route-entry anchor through `0x0048abc0`. Literal byte
`2` now looks broader: the later world-side caller at `0x00480cd0` and the linked-site refresh
helper `placed_structure_refresh_linked_site_display_name_and_route_anchor` `0x00480bb0` both
reach `0x004a01a0` with both optional endpoint-entry ids unset and that byte, so the strongest
current read is a full linked-site route-anchor rebuild between optional endpoint entries rather
than the narrower direct creation lane. The TrackLay side now gives one tighter user-facing
anchor too: the live mode field `0x00622b0c` is already grounded as `Lay single track.` `0x1`
versus `Lay double track.` `0x4`, and the small mapper `0x004955b0` collapses that state into
the endpoint-policy bytes later passed to `0x00493cf0`, so the strongest current read is
`policy 1 = single-track endpoint synthesis` and `policy 4 = double-track endpoint synthesis`.
Bytes `1/2` are still the ones that enable the
auxiliary tracker lane in `0x004a01a0`, while byte `4` now reads more narrowly as the larger
company-side endpoint-synthesis charge inside `0x00493cf0`, because that helper feeds `-1`
versus `-2` into the saturating company counter helper `0x00423ec0` on `[company+0x7680]`
rather than skipping the company branch entirely. That counter is tighter now too: nearby
company initialization seeds it to `50` when scenario byte `0x4aaf` is enabled and to sentinel
`-1` otherwise, while the companion getter `0x004240a0` returns either the live counter or fixed
fallback `29999`. Current language-table correlation also gives `0x4aaf` a stronger
player-facing meaning: it is the live gate behind `Company track laying is limited...` and the
event variable label `Company Track Pieces Buildable`. So the current strongest read is
available track-laying capacity, not an abstract company route-budget. That site-side helper
also closes one adjacent ownership gap: beneath
`placed_structure_finalize_creation_or_rebuild_local_runtime_state` `0x0040ef10`, it rebuilds
one linked site's route-entry anchor and display-name buffer. That path is tighter now than just
“bind anchor then touch `0x006cfcb4`”: after the literal-policy-`2` rebuild succeeds it
re-enters `aux_route_entry_tracker_collection_refresh_route_entry_group_membership` `0x004a45f0`,
which can now be described more concretely. Its early prepass at `0x004a4380` can split one
mismatching adjacent subchain into a fresh tracker group; its later helper at `0x004a4ce0` can
transfer one compatible adjacent chain between neighboring groups; and the repair-side helper at
`0x004a4ff0` can reseed a whole route-entry component into a fresh tracker when the old group id
is missing or invalid. The regrouping pass also still rewrites compatible endpoint slots through
`0x004950f0` and refreshes one nearby cached-match payload band through `0x00495020` before the
helper resumes the name-buffer work. The remaining display-name side still matches the earlier
grounded text family: copy the resolved city name when available, append civic suffixes
`Township`, `New`, `Modern`, or `Renaissance`, append `Service Tower` or `Maintenance Facility`
on the linked-instance class branches, and otherwise fall back through the older
`Junction`..`Center` and `Anytown` text families.
The higher owner-refresh side of that same tracker family is tighter now too. The reusable gate
at `0x004a4c00` no longer looks like a stray predicate: it explicitly requires both route-entry
trackers to keep matching cached fields `+0x18/+0x1c/+0x1d/+0x1e` and both route entries to keep
their special side fields `+0x20e/+0x222` unset before adjacent-chain transfer is allowed. The
collection-wide traversal sweep at `0x004a5fc0` is bounded now as the connected-component refresh
owner over tracker field `+0x0c`, with a temporary queue at `[this+0x94]` and direct fallback
into the reseed helper `0x004a4ff0` whenever one neighboring route entry has lost valid tracker
ownership. Above both of those sits `aux_route_entry_tracker_collection_refresh_owner_adjacent_compatible_group_links`
`0x004a6360`, which now reads as the owner-side latch-change refresher invoked from
`0x00494fb0`: it starts from one owner route-entry id, confirms both bound endpoint entries agree
on the boolean class state implied by route-entry byte `+0x44`, and then probes both endpoint
sides for adjacent route-entry groups that can be absorbed through the `0x004a4c00 -> 0x004a4ce0`
gate-and-transfer pair. The sibling query side is bounded now too:
`aux_route_entry_tracker_collection_query_component_label_by_tracker_id` `0x004a6320` is the
dirty-aware accessor for tracker field `+0x0c`, while
`aux_route_entry_tracker_dispatch_route_entry_pair_metric_query` `0x004a65b0` is the remaining
mode-switched lower metric dispatcher beneath the heavier chooser at `0x004a6630`, forwarding
fixed route-entry-pair candidate sets into either `0x004a5280` or `0x004a5900` depending on the
shared hundredths-scaled build-version query
`runtime_query_hundredths_scaled_build_version` `0x00482e00` over `0x006cec74`. The current
caller thresholds `>= 0x67`, `>= 0x68`, `>= 0x69`, and `>= 0x6a` now line up with executable
build values `1.03`, `1.04`, `1.05`, and `1.06`, and the version source itself can come from
the multiplayer companion path as well as the local executable, so this split is no longer
best-read as a time- or era-side cutover at all. It now reads more cleanly as a pre-`1.03`
versus `1.03+` route-metric compatibility dispatcher. That lower split is tighter now too:
`0x004a5280` is the weighted recursive branch with heuristic ordering, per-tracker best-cost
cache `0x006cfcac`, and prune threshold `0x006cfcb0`, while `0x004a5900` is the alternate
recursive neighbor-walk branch that stays within compatible component labels through
`0x004a62c0` and accumulates step and mismatch penalties over route-entry links
`+0x206/+0x20a/+0x20e`. Above both of them,
`aux_route_entry_tracker_query_best_route_entry_pair_metric_with_endpoint_fallbacks`
`0x004a6630` is now bounded as the real chooser: direct fixed-pair query when both entries pass
`0x0048b870`, otherwise endpoint-pair fallback across the two tracker groups.
The adjacent route-style rebuild side is tighter now too: the same build-version family reaches
`placed_structure_rebuild_route_style_candidate_scores_and_peer_links` `0x004101e0`, where build
`1.04+` keeps one `Recycling Plant` stem-specific compatibility branch alive and build `1.05+`
skips one older descriptor-side attenuation fallback. There is also one neighboring world-side
compatibility lane now bounded below the same family: `placed_structure_collect_connected_component_tile_bounds_with_version_gate`
`0x004160c0` skips one older recursive component-bounds walk through `0x00415f20` on build
`1.03+` when scenario field `[0x006cec78+0x46c38]` is already active. The wrapper above that
path is bounded now too: `placed_structure_map_tile_range_to_connected_component_records_with_optional_bounds_refresh`
`0x00416170` walks the caller rectangle, maps tile keys into the component table rooted at
`0x0062ba7c`, and only re-enters `0x004160c0` when the current owner still has no cached bounds
and the local world or scenario suppressors stay clear. The higher neighboring raster side is
tighter too. `world_grid_refresh_projected_rect_sample_band_and_flag_mask` `0x00418610` is the
shared projected-rectangle helper above `world_grid_refresh_flagged_region_float_extrema_and_mean`
`0x00415020`: it refreshes the temporary sample band at `0x0062b7d0`, publishes the surviving
rectangle through `0x0044d410`, and on the single-sample path re-enters
`world_grid_toggle_flagged_mask_bit0_for_nonsentinel_rect_samples` `0x004185a0` to flip mask bit
`0x01` for the corresponding non-sentinel cells. Current grounded callers for `0x00418610` are
the neighboring placed-structure local-runtime helper `0x00418be0` and the heavier placement
validator `0x004197e0`, so this adjacent family now reads more like projected placement or local
raster prep than an unowned generic world-grid scan. The higher owner split is tighter now too.
`placed_structure_build_local_runtime_record_from_candidate_stem_and_projected_scratch`
`0x00418be0` is the broader construction or rebuild lane: resolve one candidate id from a stem,
build projected scratch through `0x00416ec0`, then publish the projected rectangle and validate
its side windows through `placed_structure_publish_projected_runtime_rect_globals_and_validate_side_windows`
`0x00416620`. That publish pass is bounded now too: it stages `0x0062b308/0x0062b30c/0x0062b310`,
validates the rectangle against route-entry coverage through
`route_entry_collection_query_rect_window_passes_entry_type_gate` `0x00494240`, can branch into
the special projected-slot picker `placed_structure_try_select_projected_rect_profile_slot`
`0x00415570`, and refreshes the compact per-cell side tables through
`world_grid_refresh_projected_rect_surface_and_region_byte_tables` `0x00414e10` before the
finished scratch is copied into one queued runtime record and the new record re-enters
`0x00416170` when its rectangle is valid. The smaller sibling
`placed_structure_clone_template_local_runtime_record_for_subject_and_refresh_component_bounds`
`0x00418a60` now reads as the current-subject clone path above the same connected-component and
mask-refresh helpers, returning the cloned local runtime record later stored into `[site+0x24e]`
by `placed_structure_refresh_cloned_local_runtime_record_from_current_candidate_stem`
`0x0040e450`. The higher wrapper above that clone path is bounded now too:
`placed_structure_collection_refresh_local_runtime_records_and_position_scalars` `0x004133b0`
first drains the temporary site-id queue rooted at `0x0062ba64/0x0062ba6c/0x0062ba70` through
`placed_structure_local_runtime_site_id_queue_count` `0x00414480` and
`placed_structure_local_runtime_site_id_queue_pop_next` `0x00413f50`, rebuilding one cloned
local-runtime record per queued placed structure through `0x0040e450`, and only then sweeps all
live placed structures through the side refresh helper
`placed_structure_refresh_local_runtime_position_triplet_and_linked_anchor_followon` `0x0040ee10`.
The last lower side reads are tighter now too. `0x0040e450` first seeds the projected-slot cache
through `placed_structure_cache_projected_rect_profile_slot_id` `0x00414470` before it re-enters
`0x00418a60`, and the broader stem-based builder at `0x00418be0` now has one named optional side
renderer instead of an anonymous callsite:
`placed_structure_render_local_runtime_overlay_payload_from_projected_bounds` `0x00418040`.
The side refresh split is bounded now too. `0x0040ee10` publishes one local position or scalar
triplet through the shared setter `0x00530720`, then tails into
`placed_structure_refresh_linked_site_anchor_position_triplet_for_local_runtime` `0x0040e360`;
that smaller follow-on only runs on the current subtype-`1`, class-`3`, linked-site branch, and
recomputes one local-runtime triplet from the linked peer's route-entry anchor when that anchor
is still live. The heavier sibling above that side refresh is bounded now too:
`placed_structure_set_world_coords_and_refresh_local_runtime_side_state` `0x0040eba0` is the
world-coordinate mutation helper that recomputes `[site+0x388]` and `[site+0x38c]`, rewrites the
world-grid owner mapping through `0x0042c9f0` and `0x0042c9a0`, updates the subtype-`4`
proximity-bucket family when needed, rebuilds the same local position or scalar triplet, and
then tails into the linked-site anchor follow-on at `0x0040e360`.
The sibling policy-`1` side is tighter now too. The constructor lane no longer stops at “one
linked site id at `[site+0x2a8]`”: the subtype-`1` branch in
`placed_structure_construct_entry_from_candidate_and_world_args` `0x0040f6d0` now clearly
allocates that linked record through
`placed_structure_collection_allocate_and_construct_linked_site_record` `0x00481390`, whose lower
constructor is `placed_structure_construct_linked_site_record_from_anchor_and_coords`
`0x00480210`. That lower constructor seeds the linked record's own id and anchor-site id, clears
the local route-anchor and display-name fields, projects the anchor footprint into world space,
and then either binds an already-covered route entry through `0x00417b40` or falls through into
the neighboring policy-`1` route-entry synthesis family around `0x00493cf0` before rebinding the
chosen route entry through `0x0048abc0`.
The cleanup side is tighter now too. Linked-site removal now has a bounded owner at
`placed_structure_collection_remove_linked_site_record` `0x004813d0`: it resolves the linked
record through `0x006cec20`, runs the per-record teardown
`placed_structure_teardown_linked_site_runtime_state_before_removal` `0x00480590`, removes the
live entry from the collection, and only then re-enters the still-bounded company-wide follow-on
at `0x00429c10` when the removed record passed the narrower transit-like latch. That per-record
teardown is no longer just “clear some scratch fields.” It now clearly clears the route-style
scratch lane, clears the five proximity buckets at `[site+0x590..0x5b8]`, detaches or invalidates
the current route-entry anchor, frees the three per-site byte arrays at `[site+0x24..0x2c]`,
clears this site's indexed byte from the corresponding arrays of later placed-structure records,
and then re-enters `0x00436040` with the current site id.
That company-side follow-on is no longer just one opaque callback either. It is now bounded as
`company_collection_refresh_active_company_linked_transit_site_peer_caches` `0x00429c10`, which
walks the active company roster and re-enters
`company_rebuild_linked_transit_site_peer_cache` `0x004093d0` on each company. That per-company
fast pass stamps a refresh tick at `[company+0x0d3e]`, clears and repopulates the
placed-structure-side cache cells addressed through `[site+0x5bd][company_id]`, marks the
eligible linked transit sites for that company, allocates one `0x0d`-stride peer table for each
eligible site, and fills those peer rows from
`aux_route_entry_tracker_query_best_route_entry_pair_metric_with_endpoint_fallbacks`
`0x004a6630`. That helper no longer reads as one anonymous route sweep: it either uses the fixed
pair directly or falls back across tracker endpoint combinations before returning the winning
route-entry id, one route-step count, and one companion mismatch count. The fast cache now reads
more cleanly too: peer-record dword `+0x05` stores that step count, while float `+0x09` stores
the normalized continuity share derived from `(steps - mismatches) / max(steps, 1)`, not a raw
delta-per-step ratio. The
adjacent timed wrapper `company_service_linked_transit_site_caches` `0x00409720` now shows the
cadence too: `0x004093d0` is the shorter-interval refresh, while the older heavier sibling at
`0x00407bd0` was only revisited on the longer interval.
That heavier sibling is now bounded too:
`company_rebuild_linked_transit_autoroute_site_score_cache` `0x00407bd0` no longer looks like a
generic tail refresh. It reuses the fast peer tables, rebuilds candidate-local amount bands plus
normalized issue-opinion scales, and then folds the peer-side route metrics back into three
per-site cache floats with a cleaner split:
`+0x12` is the raw surviving site-score total,
`+0x0e` is the continuity-and-step-weighted companion total,
and `+0x16` is the promoted final site-ranking lane chosen from the strongest grouped candidate
bands.
That also closes most of the cross-version impact question:
the pre-`1.03` versus `1.03+` tracker metric split now looks like it mainly perturbs the weighted
`+0x0e` lane and the promoted `+0x16` lane, not the raw `+0x12` total.
That final lane then feeds the neighboring selectors
`company_select_best_owned_linked_transit_site_by_autoroute_score` `0x00408280` and
`company_build_linked_transit_autoroute_entry` `0x00408380`. That makes the company-side follow-on
read more like a linked-transit autoroute cache family than a generic company maintenance pass.
The neighboring reachability gate is tighter now too:
`company_query_cached_linked_transit_route_anchor_entry_id` `0x00401860` caches one company-side
route-entry anchor, and
`placed_structure_is_linked_transit_site_reachable_from_company_route_anchor` `0x004801a0`
uses that anchor to decide whether a foreign linked transit site can still participate in the
current company's fast peer cache.
The first direct train-side consumer above that cache family is bounded now too:
`train_try_append_linked_transit_autoroute_entry` `0x00409770`. After servicing the owning
company's caches, it asks `0x00408380` for one staged `0x33`-byte route entry using the train's
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.
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`
`0x00408f70`, and then rebalance that roster through
`company_balance_linked_transit_train_roster` `0x00409950`.
The aggregate helper no longer reads as a raw sum either:
it starts from the site-cache `+0x12` totals, converts that into one tentative roster target
through year and site-count ladders, and on build `1.03+` adds one special distance-side scaling
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.
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.
After that it fills any remaining deficit by either packaging multiplayer opcode `0x75` or
locally re-entering
`company_try_add_linked_transit_train_and_publish_news` `0x00409830`. The two visible news
helpers under it are bounded too: `0x00409830` emits RT3.lng `2896` for a newly added train,
while `company_publish_train_upgrade_news` `0x00409300` emits RT3.lng `2897` for the upgrade
branch.
The subtype-`4` sibling side is bounded now too. The nearby-site bucket family now has:
`placed_structure_append_nearby_transit_site_distance_bucket_entry` `0x0047fdb0`,
`placed_structure_remove_site_id_from_proximity_bucket_lists` `0x0047dd10`, and
`placed_structure_clear_proximity_bucket_lists` `0x0047dcd0`, plus the two collection sweeps
`placed_structure_collection_append_site_into_all_proximity_bucket_lists` `0x00481480` and
`placed_structure_collection_remove_site_id_from_all_proximity_bucket_lists` `0x004814c0`.
Current evidence says those five buckets store `(peer site id, distance)` pairs for nearby
station-or-transit peers, grouped through the five-way classifier at `0x0040d350`. The older
stream-backed side is bounded too: `placed_structure_collection_load_dynamic_side_buffers_from_stream`
`0x00481430` walks the live placed-structure collection and re-enters
`placed_structure_load_dynamic_side_buffers_from_stream` `0x0047d8e0`, which repopulates the
route-entry list, the three per-site byte arrays, the five proximity buckets, and the trailing
scratch band from the caller-supplied persistence stream.
The linked-site route-entry list itself is tighter now too. The refresh or teardown branch at
`0x0040e102` re-enters `placed_structure_remove_route_entry_key_and_compact` `0x0047d810`, which
removes one matching `u16` key from the six-byte list rooted at `[site+0x462]/[site+0x466]`,
compacts the surviving entries into a replacement buffer, and decrements the stored route-entry
count.
The broader company-side owner above these pieces is tighter now too. The periodic service pass
`company_service_periodic_city_connection_finance_and_linked_transit_lanes` `0x004019e0` now
reads as the current outer owner for this branch: it sequences the city-connection announcement
lanes, the linked-transit train-roster balancer, the acquisition-side sibling
`company_try_buy_unowned_industry_near_city_and_publish_news` `0x004014b0`, the annual finance-policy helper
`company_evaluate_annual_finance_policy_and_publish_news` `0x00401c50`, and the shorter-versus-
longer linked-transit cache refresh tail through `0x004093d0` and `0x00407bd0`. That outer pass
also has one tighter temporary-state role now: it clears company bytes `0x0d17/0x0d18/0x0d56`,
mirrors `0x0d17` into scenario field `0x006cec78+0x4c74` only while the earlier route-building
side runs, and restores the original scenario value on exit. Current evidence now ties `0x0d17`
to the shared preferred-locomotive chooser `0x004078a0`: the override is only armed when that
helper picks one locomotive whose engine-type dword is `2`. That engine-type lane now best reads
as electric rather than an unnamed class slot, because the linked approval helper around
`0x0041d550` now reads as a real locomotive-era and engine-type policy gate, dispatching the same
`0/1/2` field across three scenario-opinion lanes while the local player-facing engine-type
family is explicitly `Steam / Diesel / Electric`. That same gate also now ties the later scenario
bytes `0x4c97..0x4c99` back to the editor-side `Locomotives` page rather than treating them as
anonymous availability flags: they are the live `All Steam Locos Avail.`, `All Diesel Locos
Avail.`, and `All Electric Locos Avail.` policy bytes behind `0x004cd680` / `0x004cf0d0`. The
current logic is also tighter than a plain override tier: a positive engine-family opinion result
can carry the gate by itself only while none of those three editor bytes is enabled; once any of
them is nonzero, `0x0041d550` instead requires one matching intersection between the record-local
family bytes and the enabled editor family bytes. The `WhaleL` carveout is narrower now too:
current data-file correlation ties that stem to the `Orca NX462` / `WhaleL_NE` locomotive family,
and it explicitly zeros that positive-opinion result before the later family-availability checks,
so it loses the shortcut rather than gaining a special approval path. The same
chooser now also has a bounded fallback below it, `locomotive_collection_select_best_era_matched_non_electric_fallback_id`
`0x00461cd0`, which explicitly skips engine-type `2` and chooses the lowest-penalty remaining
locomotive by era mismatch and approval gates. The route-search side is tighter too: this
electric-only override now clearly feeds the first path-sweep branch in `0x0049bd40`, forcing the
larger `1.8` initial quality multiplier instead of `1.4`, which is the same branch otherwise
chosen by explicit route-policy byte `4`. So the later annual finance helper is reading
same-cycle side-channel state from the earlier city-connection and linked-transit branches, not
unrelated long-lived finance fields. The inner
finance helper is not debt-only either. Current grounded outcomes include bankruptcy news
`2881`, the debt restructure family `2882..2886`, a later share-repurchase headline `2887`, and
the dividend-side adjustment branch. The main commit verbs under that helper are now grounded too:
`company_repay_bond_slot_and_compact_debt_table` `0x00423d70`,
`company_issue_bond_and_record_terms` `0x004275c0`,
`company_repurchase_public_shares_and_reduce_capital` `0x004273c0`, and
`company_issue_public_shares_and_raise_capital` `0x00427450`. The threshold side is tighter now
too. The earliest creditor-pressure lane requires scenario mode `0x0c`, the bankruptcy toggle
`[0x006cec78+0x4a8f]` to be clear, at least `13` years since `[company+0x163]`, and at least
`4` years since founding year `[company+0x157]`; it then scans the last three years of the
derived net-profits and revenue lanes `0x2b` and `0x2c`, chooses one negative pressure ladder
`-600000 / -1100000 / -1600000 /
-2000000` from the current slot-`0x2c` bands around `120000 / 230000 / 340000`, requires the
broader support-adjusted share-price or public-support scalar at least `15` or `20` depending on
whether all three sampled years failed, checks the current fuel-cost lane in slot `0x09` against
`0.08` times that ladder, and requires the
three-year slot-`0x2b` total to clear one final `-60000` gate before it falls into the
bankruptcy commit and RT3.lng `2881` headline.
The middle debt-capital layer is split more clearly now too. With `[+0x4a8b]` clear, one annual
bond lane first simulates full repayment through `company_repay_bond_slot_and_compact_debt_table`
and then uses the post-repayment cash window with fixed `-250000` and `-30000` thresholds plus
the broader linked-transit train-service latch `[company+0x0d56]` to decide whether to append one
or more `500000` principal, `30`-year bonds. The repurchase lane is separate again: when the
city-connection announcement-side latch `[company+0x0d18]` is set, growth setting `2` does not
suppress it, and `[+0x4a87]` is clear, it starts from one `1000`-share batch, can replace its
default `1.0` factor with one linked-chairman personality scalar, scales that by `1.6` when
growth setting `1` is active, and then runs one `800000` stock-value gate plus one
support-adjusted-share-price-times-factor-times-`1000`-times-`1.2` affordability gate before the
repeated `1000`-share buyback commits behind RT3.lng `2887`. The ordering above this helper is
tighter now too:
`company_service_periodic_city_connection_finance_and_linked_transit_lanes` clears those latches
first, runs the city-connection and linked-transit branches, and only then enters the annual
finance helper, so these look like same-cycle reaction gates rather than long-lived balance-sheet
flags.
After the earlier debt or bankruptcy outcomes stay inactive, the later stock-capital lane also
has a tighter bounded shape now too: it only opens on build `1.03+`, only after the earlier
bankruptcy, bond, and repurchase outcomes stay inactive, and with the bond and stock toggles
`[+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
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.
The dividend side is bounded too: it requires the dividend toggle `[0x006cec78+0x4a93]` to be
clear, mode `0x0c`, at least `1` year since `[company+0x0d2d]`, and at least `2` years since
founding, then averages the last three years of the net-profits lane `0x2b`, folds in the
unassigned-share pool and the current `0x0d` band, applies the map-editor building-growth
setting `[0x006cec78+0x4c7c]`, treats growth setting `1` as a `0.66` scale-down and setting `2`
as a zeroing pass on the current dividend, quantizes surviving adjustments in tenths, and
finally clamps against
`company_compute_board_approved_dividend_rate_ceiling` `0x00426260`.
The linked-transit route-seeding side has one tighter sibling now too:
`company_reset_linked_transit_caches_and_reseed_empty_train_routes` `0x00401940`. It clears the
two company-side linked-transit cache timestamps, forces one immediate cache rebuild through
`0x00409720`, strips route lists from company-owned trains in modes `0x0a/0x13`, and then
re-enters `train_try_append_linked_transit_autoroute_entry` `0x00409770` only when a train's
route list has become empty.
On the wider chooser question, the current evidence is also tighter than before: every recovered
external owner of `0x00402cb0` is still in the city-connection family, so the two later direct
placement lanes currently read as city-connection fallback behavior rather than a broadly shared
world placement service.
It can still unwind through route-state cleanup without committing new placed structures, so the
exact lower helper semantics are not fully closed, but the broader chooser is no longer
anonymous and its main policy split is now visible. The two lower helpers directly under those
commit lanes are bounded now too:
`placed_structure_project_candidate_grid_extent_offset_by_rotation` `0x00417840` is the shared
projected-footprint offset helper over candidate bytes `[candidate+0xb8]` and `[candidate+0xb9]`,
and `placed_structure_validate_projected_candidate_placement` `0x004197e0` is the shared
go-or-no-go validator that checks company, territory, world-tile, and footprint occupancy state
before either direct-placement commit is allowed to fire. Its strongest current subtype branch is
a station-attachment or upgrade-style lane keyed by `[candidate+0x32] == 1`, which now has the
concrete failure family `2901..2906`: blocked upgrade footprint, ground not flat enough, not
your track, insufficient track-laying capacity, cannot connect to existing track, and ground too
steep. That tightens the chooser materially without yet proving that the validator is
station-only for every caller.
The recurring outer owner is tighter now too:
`placed_structure_collection_refresh_quarter_subset_route_style_state` `0x00413580` walks every
fourth live placed structure from a scenario-time-derived offset and re-enters the per-site
rebuild with stack flag `0`, giving the route-style lane a concrete recurring maintenance sweep
under `simulation_service_periodic_boundary_work` rather than only a floating caller note. One
neighboring helper is now bounded on the message side too:
`shell_building_detail_handle_subject_value_row_band_action` `0x004ba270` switches over the
clicked row family `0x7d07..0x7d14`, treats subject bytes `+0x21/+0x22/+0x23` as one current
selection plus one bounded low/high pair, increments the family dirty latch at `0x006cfe0c` on
change, and republishes the refreshed value through the shared shell control helper on code
`0x66`. One neighboring helper is now bounded on the side-list path too:
`shell_building_detail_propagate_selected_subject_state_into_side_list` `0x004b9ec0` walks the
sibling list owner at `0x006cfe08`, copies the active subject state into each side-list record,
mirrors the current service or capability id at `+0x24`, and preserves the `0x40/0x20/0x10`
subflags from the active subject. That means the value-row actions and later selector rows now
read as propagating one shared building-detail state across the sibling list rather than only
mutating one isolated subject record. One neighboring helper is
now bounded separately too: `shell_building_detail_refresh_subject_pair_value_rows` `0x004bad20`
owns the mutually exclusive value-row pairs `0x7d07/0x7d08`, `0x7d11/0x7d12`, and
`0x7d13/0x7d14`, choosing among them from the same selected-subject flag byte and payload fields
at `+0x22/+0x23`, while the larger cargo-or-service row owner also gates the extra visual lanes
`0x7d6a`, `0x7d6b`, and `0x7d9d` from that same subflag family. The asset-string block is tighter
too: that branch family now explicitly uses `AnyCargo.imb`, `AnyFreight.imb`, `PassMail.imb`,
`Caboose.imb`, and `Dining.imb`, with the bit-`0x20` special lane already aligned to
`Caboose.imb` and the sibling bit-`0x10` special lane now aligned to `Dining.imb`. The larger
`0x7f58..0x801f` band is no longer just a styled row family either:
`shell_building_detail_present_flagged_service_capability_popup` `0x004b9fd0` is now grounded as
its explanatory popup callback. It resolves either one fixed express-side row from `0x00621e04`
or one active candidate or service id from `[subject+0x24]`, then formats one popup through the
shell message-box path. The neighboring refresh helper `shell_building_detail_refresh_flagged_service_capability_rows`
`0x004b9a20` is tighter now too: `0x7d07..0x7d1c` is not one anonymous block, but a real mask
partition over subject bits `0x20` and `0x10`, with one zero-mask pair, one bit-`0x20`-only
pair, one exclusive-or pair, and later one-bit and two-bit indicator rows. RT3.lng now closes
the fixed popup text family too: the single-line branch uses
`3922` `%1\nLoads available at %2: %3`, while the richer ordinary-candidate branch uses
`2981` `%1\nLoads available at %2: %3 Current Price: %4` and can append
`2982` `Price at next station, %1: %2 (%3%4)`. The selector band is narrower too: current
refresh-side evidence shows `0x7f58..0x801f` as one selected-ordinal highlight family over the
three fixed express rows plus the ordinary active-candidate rows, not as a generic unstructured
list. The neighboring `0x8020..0x8051` band is tighter too: it is primarily the matching
remove-entry family for the selected subject's live id list, with two special row indices
re-routing into the `0x7d0f/0x7d10` subflag-clearing path instead of ordinary list compaction
when the current `0x20/0x10` service-bit combination demands it. That means the exact captions
are no longer broadly open across the whole selector family: the fixed express-side rows, the
mask partitions, and the add/remove structure are grounded, and the remaining caption gap is
mostly the ordinary candidate rows further down the same band. The top-level toggles are
tighter now too: the paired
`0x7d02/0x7d03` controls are the real mode switch over subject bit `0x40`, choosing between the
bounded pair-value branch and the current-selection/status branch around `0x7d0d/0x7d0e`, while
the smaller `0x7d0f/0x7d10` controls flip the same special-service subflags later rendered as
`Caboose` and `Dining Car`. One adjacent control is tighter now too: the extracted
`BuildingDetail.win` resource contains the plain-English line `Set the initial cargo amount for
'Disable Cargo Economy' scenarios.`, and the `0x7d01` plus `0x7d09/0x7d0a` message-side branch
can mirror the current subject or selection through
`shell_building_detail_submit_aux_owner_subject_sync_request` `0x004b9e10` into the auxiliary
owner queue at `[0x006cd8d8+0x8f48]`, with side-owner presence now explicitly grounded through
`shell_has_auxiliary_preview_owner` `0x00434050`. That queued request is tighter too: both
current callsites forward the same side-list mirror latch at `[0x006cfe08+0x0c]`, so the
auxiliary owner now clearly sees not just the staged subject but also whether the local
`BuildingDetail` side-list is in mirrored-subject mode. The same `0x7d01` lane also now has one
clear rejection note: localized id `3587` `This option is only available by following the
tutorial.` now sits behind the active tutorial flag at `0x006d3b4c` and the cached previous
tutorial expected-control id at `0x00622b38`, while the neighboring tutorial helper
`tutorial_advance_step_and_refresh_expected_control_ids` `0x00516be0` now grounds
`0x00622b34/0x00622b38/0x00622b3c` as the current and previous expected-control cache rather
than anonymous globals. The last field is tighter now too: `0x00622b3c` is currently best read
as the active tutorial step's alternate-accepted companion control id, because the generic shell
control path compares clicked control ids against it directly and suppresses the `3587` tutorial
rejection when they match. That does not fully close the player-facing caption bind for every
control, but it does bound the neighboring side-owner sync and tutorial-rejection lane instead
of leaving it as anonymous glue.
The extra pre-insert gate is narrower than it
first looked. It is now grounded as tutorial-only:
`tutorial_validate_train_route_station_indicator_step` `0x00516d00` checks the current tutorial
step from the shell tutorial descriptor table at `0x00622b48` before a live station-or-transit
site id can be committed into the staged route entry, and the currently accepted steps align with
localized prompts `3777` and `3778`, the two train-routing tutorial instructions that tell the
player to click the Milan and Turin station indicators. Outside that tutorial state family, the
route-entry insertion path is not gated there. The adjacent validator is tighter now too:
`train_route_list_validate_reachability_and_station_pair` `0x004b2c10` walks that same route list,
resolves placed-structure-backed entries through the live placed-structure and route-node
collections, uses the direct route-node payload branch for the remaining entry family, and fails
with `3089..3091` when the resulting route cannot be traversed or does not preserve a valid
terminal station pair. The post-validation follow-on is bounded too:
`train_current_route_context_uses_strict_reachability_mode` `0x004a9460` is now the small shared
gate above the stricter branch, keyed off the current linked route object's downstream class type,
and `train_set_route_operating_mode_and_scalar` `0x004ab980` now reads as the shared train mode
setter beneath route editing, with the local and multiplayer insertion paths choosing mode
`0x13` only when that stricter second validation succeeds and mode `0x0a` on the looser fallback
path. The first
deeper world-mode interaction branch is now better
bounded: `GameUppermost.win` hotspots, cursor drag, held Shift state, discrete shell view-step
commands, direct keyboard turn/pan/zoom bindings, the `TrackLay.win` and `StationPlace.win`
world-command surfaces, and a frame-owned hover or focus-target transition branch all feed the
same shell-controller-backed path. The remaining uncertainty has moved farther from basic
ownership: the hover-target branch clearly exists, and `0x07d6` now looks like the shared
main-world interaction surface rather than a generic detail button for one tool family only. 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 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
`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
rebuilt family aligns with the four grouped effect lists later deep-copied through
`scenario_event_clone_runtime_record_deep_copy` `0x0042e050` during event duplication and effect
staging. The condition side is tighter now too: the tiny helper cluster
`0x0042df30/0x0042df70/0x0042dfb0/0x0042dff0` is no longer just "some adjacent list scans".
Current evidence bounds it as four predicates over the standalone `0x1e`-row condition list,
testing class bits `0x01`, `0x02`, `0x04`, or any of those bits in the static table
`0x005f3e04 + id*0x81`, with special fallback checks through event fields `[event+0x7f9]`,
`[event+0x7fa]`, and `[event+0x7f0] == 0x63`. The shell side is tighter too: vtable slot
`0x005d0cd8` now binds `shell_event_conditions_window_handle_message` `0x004d59e0`, and vtable
slot `0x005d0cf8` binds `shell_event_effects_window_handle_message` `0x004d7060`. The effects
side is tighter too: the lower helper trio is no longer anonymous. `0x004d5d00` now reads as the
effect-type selector refresh under control family `0x4fb2`, `0x004d5f50` reads as the selected
effect parameter-row repaint, `0x004d6090` is the heavier staged-effect editor refresh over the
`0x4fc7/0x4fce/0x4ff6/0x4ff9/0x4ffc/0x5041/0x5044/0x5046/0x5047` bands, and `0x004d67f0`
commits the current editor state back into the staged effect row at `[this+0x78]`. The verb side
is tighter now too: `shell_open_event_conditions_modal_and_return_result` `0x004d9dc0` and
`shell_open_event_effects_modal_and_return_result` `0x004d9e40` are the shared modal openers
above the two editor windows; `0x004da640`, `0x004da700`, and `0x004d9ed0` now read as the add,
edit, and remove verbs for standalone condition rows; `0x004da7c0`, `0x004da860`, and
`0x004da920` are the matching add, edit, and remove verbs for grouped effect rows; and
`0x004d8120` is now the heavier condition-row list panel refresh those condition-side verbs
re-enter after mutation. The conditions-side refresh split is tighter too: `0x0042d700`
aggregates standalone condition-list class or modifier flags, `0x0042d740` aggregates grouped
effect-row type flags for one selected grouped list, `0x004d9970` owns the condition-class
summary and grouped-row status bands, `0x004d77b0` owns the grouped summary-band affordance gate
for `0x4fed..0x4ff0` when selector `0x5000` lands on `0x5002`, `0x004d9d10` owns the smaller
grouped-effect territory-target affordance on control `0x500b`, `0x004d9f50` owns the selected-event mode
strip and summary text panels, and `0x004d9390` is the mode-dependent detail-row switch beneath
that strip. `0x004da0f0` is tighter too: selector `0x5001` now has the strongest current
RT3.lng fit as the condition-side `Test against...` mode above `0x004d9970`, while selector
`0x5002` has the strongest current fit as the grouped-effect-side `Apply effects...` mode.
That `0x5002` branch now clearly builds control `0x5014` from RT3.lng `1160..1164` as `to the
company/player/player (i.e. chairman)/territory for which the condition is TRUE` before
enabling the adjacent `0x5005`, `0x500a`, and `0x5014..0x501c` family. The strongest current
RT3.lng fit for the remaining visible target-scope strip is now `0x5015 = to the whole game`,
`0x5016..0x5018 = to all/human/AI companies`, `0x5019 + 0x500b = to territories`, and
`0x501a..0x501c = to all/human/AI players`; the grouped effect-row type mask matches that split
directly through bits `0x08`, `0x01`, `0x04`, and `0x02`. The
selected-event strip is tighter now too: `0x004db120` is the broader selected-event repaint and
navigation refresh above those smaller helpers, `0x004db520` and `0x004db5e0` are the previous
and next selected-event stepping verbs, `0x004db8b0` is the add-or-clone event modal helper,
`0x004dba90` is the rename verb, `0x004d9360` is the delete verb, `0x004db6a0` is the live
selected-event id setter behind control `0x4e84`, and `0x004db6f0` is the callback-binding plus
pending-selection bootstrap path that seeds the strip during window bring-up. The larger
dispatcher at `0x004dbb80` now makes the strip explicit: `0x4e85..0x4e8a` are previous, next,
add blank, clone selected, rename, and delete event, while the later grouped band commits current
summary state through `0x004d8d50` before changing grouped selector `[this+0x9c]` via `0x004dbf93`.
The selection bootstrap side is tighter too: `0x004daf40` is now the placeholder reset helper for
the selected-event summary controls `0x4eaf`, `0x4eac`, `0x4ed9`, `0x4edb`, and `0x4fdf..0x4fe2`.
The grouped target-scope side is tighter too: `0x004d8ea0` now reads as the commit helper for current
selected-event text panels before selection or grouped-action changes, `0x004d8d50` now records
the hidden selector family `0x5006..0x500e -> 0..8`, and `0x004dab60` projects that ordinal
one-to-one onto the visible grouped-effect target-scope display strip `0x5014..0x501c`. That
split is firmer now: `0x5006..0x500e` are the canonical hidden selectors that get stored into
`[event + group + 0x7fb]`, while `0x5014..0x501c` are the visible mirror rows republished from
that same ordinal rather than a second independently named selector family. The grouped row and
stored-summary refresh side is tighter too: `0x004d88f0` is now the selected grouped-effect
row-list renderer for `0x4ed5`, formatting the grouped `0x28`-byte rows through RT3.lng
`1154..1159`, and `0x004da9a0` is the current grouped-summary-state republisher that reloads
`0x500a`, `0x500b`, and visible action selection `0x5014..0x501c` from `[event + group + ...]`
before tailing back into `0x004da0f0`,
`0x004dbfca` as the grouped target-scope mode selector that persists the chosen control id into
`0x00622074`, with `0x5001/0x5002` now strongest-fit as `Test against...` and
`Apply effects...`, `0x004dbeeb` as the pending shared summary-text triplet publish helper for
`0x4eac/0x4ed9/0x4edb`,
`0x004d91e0` as the selected-event summary-header and grouped-mode commit helper above
`0x004d8d50`, and `0x004dbe7a` as the narrower `0x4ec6/0x4ec7` choice-event single-player-only
warning modal branch rooted at RT3.lng `3887`. The remaining gaps on
this lane are narrower again because the grouped-band `0x4dc09c` table now closes one earlier
overclaim: controls `0x5001/0x5002` are the only `0x4fed..0x501c` entries that route into
`0x004dbfca` on the `0xcf` side, while visible rows `0x5014..0x501c` only route to the smaller
`0x004d9d10` affordance path and the rest of `0x4ff1..0x5013` are default no-ops. The open
question is therefore no longer whether those visible target-scope rows are direct selector verbs;
current evidence says they are not.
The local slot records are rooted at
`[world+0x69d8]`,
`[slot+0x01]` polarity and the external role gate at `[world+0x0bc3+slot*9]` are now grounded, and
`[slot+0x03]` now looks like the distinguished primary-human-seat marker because current grounded
writes seed it only on slot zero and later logic moves it solely by whole-record compaction. The
open question is no longer whether the seeded trio lands in the visible shell company roster;
current evidence says it does, and ordinary `Start New Company` now looks like a fresh-company
allocator through `start_new_company_dialog_commit_create_company` and
`start_new_company_request_create_company`, not like the path that claims one of the seeded named
railroads. The immediate post-roster station branch is now clearly separate: current grounded
resource names and handlers put mode `8` on `StationDetail.win`, mode `5` on `StationList.win`,
and the subordinate selector helper on `StationPick.win`. The company-side ownership question has
therefore moved down a layer rather than staying open. We now have a recovered `CompanyDetail.win`
owner family through `shell_company_detail_window_refresh_controls`,
`shell_company_detail_window_construct`, and `shell_company_detail_window_handle_message`; the
same owner now has one broader bounded read-side lane too, because control `0x9470` uses
`shell_company_detail_render_financial_history_panel` to draw the five-step Revenue or Expenses or
Interest or Profit or Lifetime strip, sibling control `0x9471` reuses
`shell_format_company_financial_summary_card` through
`shell_company_detail_render_company_summary_card`, controls `0x947d` and `0x947e` now ground a
bond maturity and repay panel through `shell_company_detail_render_bond_maturity_and_repay_panel`,
control `0x9488` now grounds the debt or credit or rate summary block through
`shell_company_detail_render_debt_credit_and_rate_summary_panel`, control `0x948a` now grounds the
share-value and dividend-payout block through
`shell_company_detail_render_share_value_and_dividend_summary_panel`, while the broader six-row
per-share stock-data family is now bounded under `shell_format_company_stock_data_panel`, and the
adjacent territory selector lane is bounded through
`shell_company_detail_select_territory_access_row`,
`shell_company_detail_render_territory_access_row`,
`shell_company_detail_sync_selected_territory_from_picker`, and
`shell_company_detail_refresh_selected_territory_access_summary`; the first finance-action layer
beneath it is bounded through the bond, stock-issue, stock-buyback, and dividend-rate helpers; the
territory-access side is bounded too through
`shell_company_detail_refresh_selected_territory_access_summary`,
`shell_company_detail_buy_territory_access_rights_flow`, and the underlying company access-rights
helpers; and the full takeover and merger vote-result lane is now grounded through
`shell_resolve_chairmanship_takeover_vote_and_commit_outcome`,
`shell_present_chairmanship_takeover_vote_outcome_dialog`,
`shell_resolve_merger_vote_and_commit_outcome`, and `shell_present_merger_vote_outcome_dialog`.
The remaining company-side uncertainty is therefore narrower than before: the broader support and
valuation side is now tighter too because
`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,
`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.`
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
buttons, the station-style scroller, and the station-rotation controls. The older `Building
placement center` string 671 no longer looks like a live StationPlace control label in the current
recovered flow, because the active constructor, preview, refresh, and dispatcher paths all use
neighboring ids such as 669 and 2208 without a direct recovered lookup of 671. On save or load the
broad serialize-versus-restore split is now grounded, the non-Quicksave `.gmp/.gmx/.gmc/.gms`
families are separated, and the auxiliary `.gmt` path is at least bounded to the preview-surface
side owner. The higher-value shell-facing gap has therefore shifted upward to the remaining
semantics of the post-load generation phases, the later recurring structure-population cadence,
the deeper vote-weight formulas inside takeover and merger resolution, and the still-open meaning
of the packed simulation calendar tuple.
- CompanyDetail, tighter section ownership: the shell detail family now has an explicit
section-selector lane in addition to the read-side panels already mapped. Controls
`0x9472..0x9475` directly select the four visible CompanyDetail sections through `0x006cfe60`,
`0x9476..0x9479` are the companion visual controls for that same tab strip, and section `0` is now
bounded more tightly as the chairman or governance slice around the portrait-backed chairman band
on `0x9480` plus the dynamic overview widget `0x947f`. That widget is no longer just a vague
status line: the section-0 refresh binds it through a dedicated stack-built dynamic text path,
and the strongest current shared formatter candidate is
`shell_format_company_governance_and_economy_status_panel` at `0x004e5cf0`, which first renders a
five-line company-metric preamble through localized ids `1211..1215`: `Revenues` from slot
`0x2c`, `Profits` from slot `0x2b`, `Load miles hauled` from slot `0x17`, `Revenue per load
mile` from the derived `slot 0x2c / slot 0x17` branch, and `Average speed` from slot `0x26`
rendered through `1216` `%1 m.p.h.`. It then splits the governance summary more concretely: no
linked chairman emits `3045`, wholly owned companies emit `3046` for the scenario-selected
chairman or `3047` for another linked chairman, and investor-owned companies emit the
investor-attitude lines `3048/3049` with one adjective from the table at `0x00622170`. That
branch is no longer using unnamed helpers either: `company_get_linked_chairman_profile_record`
`0x00426ef0` resolves the linked chairman profile and `chairman_profile_owns_all_company_shares`
`0x004768c0` is the full-ownership test behind the `3046/3047` split. The salary side is tighter
too: the formatter computes one signed delta from `[company+0x14f]` and `[company+0x0d59]`, then
chooses `3050..3052` for the scenario-selected chairman or `3053..3055` for another linked
chairman depending on whether that delta is negative, positive, or zero. The bonus line is
narrower still: it only appears when the display year matches `[company+0x34f]`, using amount
`[company+0x353]` with `3056` or `3057`. It then appends the
`1218` `Economy status - %1.` tail caption and stages the adjacent selected-company report or
list help-title pairs `1219/1220` `Income Statement`, `1221/1222` `Balance Sheet`,
`1223/1224` `Haulage Report`, `1225/1226` `Stock Report`, `1227/1228` `Train List`,
`1229/1230` `Station List`, `1231/1232` `Industry List`, and `1233/1234` `Cargo List`.
Current evidence still does not recover separate `CompanyDetail.win` action controls for that
strip under `shell_company_detail_window_handle_message`, so it currently reads as staged
overview text or help content rather than as a closed launcher family. The direct `0x947f`
formatter call is still indirect, but the widget boundary is tighter too: the generic shell
helpers `shell_control_refresh_matching_dynamic_text_payload` `0x00540a47` and
`shell_control_release_dynamic_text_payload` `0x005639d2` now show that type `0x6f` controls
free or swap one heap-backed text payload and then short-circuit as a special dynamic-text case,
which strengthens the reading of `0x947f` as a display-only overview widget rather than a normal
callback control. One adjacent boundary is tighter now too: the broader overview wrapper at
`shell_render_company_overview_panel_header_and_optional_change_affordance` `0x004e5a80` owns
the fallback no-company texts `1210`, `3043`, and `3888`, styles controls `0x3f06` and `0x3f07`,
and on the narrower selected-company branch appends `3044` `Click to change company name and
logo.` plus the neighboring `1941` `Change` affordance before falling through into the shared
`0x004e5cf0` text body. That keeps the name/logo affordance outside the ordinary
`CompanyDetail.win` action dispatcher and makes the `0x947f` alignment cleaner. The message-side
action band is tighter too: `0x94b5` grounds
territory-access purchase, `0x94b6` grounds bankruptcy, `0x94cf..0x94d2` ground bond issue, stock
issue, stock buyback, and dividend-rate changes, `0x9493` routes into the destructive
company-clear helper that deactivates the selected company and clears chairman/share links,
`0x94d6` grounds bankruptcy, `0x94d7..0x94da` ground bond issue, stock issue, stock buyback, and
dividend-rate changes, `0x94db` grounds merger, `0x94dc` grounds resignation, and `0x9538` grounds
chairmanship takeover. The finance-side dialog family is tighter too: the bond-issue lane now has
the dedicated modal renderer `shell_company_detail_render_issue_bond_offer_dialog` `0x004c3560`
for underwriter terms `968..972`, the stock-issue lane has
`shell_company_detail_render_issue_stock_offer_dialog` `0x004c3b50` for the staged offer lines
`975..978`, and the buyback lane has
`shell_company_detail_render_stock_buyback_offer_dialog` `0x004c4300` for broker lines
`981..984`. The compact summary card on sibling control `0x9471` is tighter too:
`shell_format_company_financial_summary_card` at `0x004bfb30` now clearly renders `Cash:`,
`Revenue:`, and `Profits:` from company slots `0x0d`, `0x2c`, and `0x2b`, rather than one looser
unnamed finance block. The dividend lane is now split the same way:
`shell_company_detail_setup_dividend_rate_adjust_controls` `0x004c4c70` binds the paired adjust
controls `0x99e8` and `0xc0f9`,
`shell_company_detail_render_change_dividend_rate_dialog` `0x004c4e30` renders localized ids
`988..990`, and
`shell_company_detail_handle_change_dividend_rate_dialog_message` `0x004c5140` clamps the staged
dividend rate against `company_compute_board_approved_dividend_rate_ceiling` `0x00426260` and
raises localized id `991` when the board refuses a higher dividend, all before the existing
company commit path. All four finance verbs now converge through the shared
callback-driven modal opener `shell_open_custom_modal_dialog_with_callbacks` `0x004c98a0`, which
is also reused by the multiplayer staged text-entry lane. The front controls in section `0` are
tighter too: `0x948b` is a
tutorial-guarded escape or back control that shows localized id `3724` `This option is disabled in
the tutorial.` before falling back to the shell detail-manager escape path, `0x9491` and `0x9492`
only restyle the paired visuals `0x948f` and `0x9490`, and `0x9494` opens localized id `3635`
`Enter the amount that your company's cash should be` and writes the accepted value directly into
the selected company cash pair. The neighboring debt section is tighter now too: controls
`0x947d` and `0x947e` no longer read as one-off bond widgets, but as the owners of two repayable
bond-slot row bands, `0x94e8..0x950f` and `0x9510..0x9537`. Those row controls now clearly
converge on the same repayment path in the message dispatcher: they reject unaffordable repayment
through localized id `2990`, open the early-repayment confirmation rooted at `2991`, and then
either commit through `company_repay_bond_slot_and_compact_debt_table` `0x00423d70` or package
the request through the multiplayer shell transport. The render-side owner is tighter too:
`shell_company_detail_render_bond_maturity_and_repay_panel` formats `Due %1` and `Repay this
bond.` for the selected debt slot while the tiny binder
`shell_company_detail_bind_bond_row_band_for_active_panel` switches between the two row bands.
Current `0xcb` dispatch does not treat `0x948f`, `0x9490`, `0x94d4`, or `0x94d5` as standalone
action cases. The message-side jump table now makes that passive/action split explicit too: in the
dispatch byte map rooted at `0x004c6640`, controls `0x94d6..0x94dc` map to cases `0x06..0x0c`,
control `0x9538` maps to case `0x0d`, and the neighboring companion rows `0x94d4` and `0x94d5`
stay on the default path. The refresh-side ownership is tighter too: the helper now explicitly
loops over `0x94d4..0x9537` as the selected-company-owned band and over `0x9538..0x959b` as the
linked-chairman-owned band, and those two loops do not use the same style polarity.
`0x94d4..0x9537` take style `0x65` when the selected company matches the scenario-selected
company and `0x87` when it differs, while `0x9538..0x959b` take style `0x87` when the selected
company's linked chairman matches the scenario-selected chairman and `0x65` otherwise. The
selected-company action side
is tighter now too: scenario toggle `0x006cec78+0x4a8f` re-enables bankruptcy `0x94d6` together
with passive companion row `0x94d4`, `+0x4a8b` re-enables issue bonds `0x94d7` together with
passive companion row `0x94d5`, `+0x4a87` re-enables stock issue and stock buyback
`0x94d8..0x94d9`, `+0x4a93` re-enables dividend `0x94da` together with the same passive
companion row `0x94d5`, `+0x4adb` re-enables merger `0x94db`, `+0x4acb` re-enables resignation
`0x94dc`, and `+0x4acf` re-enables chairmanship takeover `0x9538`. That makes `0x94d4/0x94d5`
read more like passive companion or heading widgets than hidden verbs. The constructor boundary
is tighter too: current `CompanyDetail.win` setup still only binds explicit callbacks for
`0x9470`, `0x9471`, `0x947d`, `0x947e`, and `0x948c..0x948e`, not for the wider section-0 row
bands. That keeps the remaining `0x94d4..0x959b` content looking more like resource-defined
display rows that are gated and restyled by refresh than like individually code-rendered widgets.
That leaves the main remaining CompanyDetail-specific shell edge at the exact `0x947f` formatter
binding plus the still-unsplit render-side governance rows inside `0x94d4..0x959b`.
- Adjacent `LoadScreen.win` report family: the neighboring shell lane around controls
`0x3ef6..0x4073` is now separated from `CompanyDetail` instead of being treated as one more
extension of the `0x947f` overview path. The real outer owner is
`shell_load_screen_window_construct` `0x004ea620`, which binds `LoadScreen.win`, randomizes the
`LoadScreen%d.imb` background family, stores the singleton at `0x006d10b0`, and seeds the first
visible page-strip controls. Above the older page-specific work, the real message owner is now
`shell_load_screen_window_handle_message` `0x004e3a80`: it owns page id `[this+0x78]`,
page-local substate `[this+0x7c]`, page-kind `[this+0x80]`, current company `[this+0x88]`,
current chairman profile `[this+0x8c]`, display year `[this+0x9c]`, and the page-local report
row latch `[this+0x118]`, then fans back into the shared selector
`shell_load_screen_select_page_subject_and_refresh` `0x004e2c10`, the company-step helper
`0x004e3a00`, and narrower page branches such as `0x004e45d0`. The matching render-side owner is
now bounded too: `shell_load_screen_render_active_page_panel` at `0x004ea060` formats the common
heading and panel frame, then switches on page id `[this+0x78]` and hands control down into the
active page body. That older branch is now demoted to what it actually is:
`shell_load_screen_profile_stock_holdings_page_handle_message`, the page-specific handler beneath
the stock-holdings slice. Inside that same family,
`shell_load_screen_render_profile_stock_holdings_summary_panel` at `0x004e5300` grounds the
selected-profile holdings page: it resolves the current chairman profile from `[this+0x8c]`,
renders the top summary rows `1204` `Stock Value:`, `1205` `Total Assets:`, and
`1206` `Stock Holdings:`, then walks the active company roster and formats one row per positive
holding through `1201` `Click to view details on %1.`, `1207` `%1 Shares`, and `1208` `%1 Value`,
falling back to `1209` `None` when no positive holdings survive. It also appends `3029`
`Click to change player name and portrait.` plus the adjacent `1941` `Change` affordance only
when the rendered profile matches the scenario-selected chairman. The earlier pages are tighter
now too: `0x004e68e0` is the selected-company financial ranking page using the active company
roster plus `1235..1245` for revenue, profit, cash, track mileage, and report affordances; and
`0x004e6ef0` is the active-chairman wealth ranking page using the chairman profile collection
plus `1237`, `1241`, `1246..1250` for cash, stock, total, and purchasing-power style comparisons.
The later sibling renderers are broader than that one holdings page now too: `0x004e7670` is the
selected-company train list page using `1235..1267`, `0x004e8270` is the selected-company
building list page using `1268..1278`, `0x004e8bb0` is the selected-company station list page
using `1279..1288`, and `0x004e9460` is the map-wide cargo list page using `1289..1298` over the
live candidate collection rather than one company roster. The last broad early-page owner is
tighter now too: `0x004e9b20` is the shared multi-year company report-table renderer for page
`4` `Income Statement`, page `5` `Balance Sheet`, and page `6` `Haulage Report`, all driven from
`0x004ea060` with one caller-supplied mode byte and yearly company rows built through
`company_read_year_or_control_transfer_metric_value`. The row families are bounded too:
income-statement rows `1301..1315`, balance-sheet rows `2816` and `1317..1322`, and
haulage-report rows `1323..1335`. The only special rows inside that family are now tighter too:
`0x00425880` and `0x004258c0` provide the negative-cash and positive-cash interest-rate inserts
for the `%1/%2` placeholders in strings `2815` and `2816`, so they are no longer anonymous
private math blobs. The adjacent early siblings are tighter now too: `0x004e5130` is the
selected-company `Stock Data` page wrapper that falls back through `1299` and otherwise reuses
`0x004c0160` to render the `Largest Shareholders`, `Shares`, and `Per Share Data` family;
`0x004e6ef0` is the `Player List` page; `0x004e5300` is the `Player Detail` holdings page; and
`0x004e51ea` is the `Game Status` briefing panel that pulls current scenario briefing text from
the live scenario text store and appends the `1772/1773` `Briefing` affordance. The active-page
renderer at `0x004ea060` is now tighter too because its 13-byte page descriptor table at
`0x006220a0` has been decoded directly as `{ page kind, title string id, `0x3ef8` backlink
page, selected-company-header flag }`. The currently grounded rendered title order is:
`XXX`, `COMPANY OVERVIEW`, `COMPANY LIST`, `INCOME STATEMENT`, `BALANCE SHEET`,
`HAULAGE REPORT`, `STOCK DATA`, `PLAYER LIST`, `PLAYER DETAIL`, `GAME STATUS`,
`TRAIN LIST`, `TRAIN DETAIL`, `STATION LIST`, `STATION DETAIL`, `CARGO LIST`,
and `INDUSTRY LIST`. Its live body bindings are now bounded too: page `0` falls back to
`1203` `Unable to display page`, page `1` is the company overview wrapper, page `2` is the
company list page, pages `3..5` are income statement, balance sheet, and haulage report, page
`6` is stock data, page `7` is player list, page `8` is player detail, page `9` is game status,
page `0x0a` is train list, page `0x0b` currently falls back to `1203`, page `0x0c` is station
list, page `0x0d` currently falls back to `1203`, page `0x0e` is cargo list, and page `0x0f`
is industry list. The row-click path is tighter now too: player-list rows re-enter page `8`
directly, but train, station, and industry rows leave `LoadScreen.win` through the shell
detail-panel manager at `0x004ddbd0` instead of switching to title-table pages `0x0b` or
`0x0d`. Page `0` is tighter now too: its descriptor is kind `0`, title `1200` `XXX`, backlink
`0`, and header flag `0`, and no current post-constructor selector path has been recovered for
it. The descriptor side now also bounds the only known reverse route for the dormant detail
titles: `0x3ef8` is the table-driven backlink affordance, so if page `0x0b` or `0x0d` were ever
selected, the known reverse path would return to train-list page `0x0a` or station-list page
`0x0c` respectively rather than through a separate detail-only owner.
The launcher side is tighter too: current grounded `shell_open_or_focus_load_screen_page`
callers cover pages `1`, `2`, `3`, `4`, `5`, `6`, `7`, `9`, `0x0a`, `0x0c`, `0x0e`, and `0x0f`,
and no current recovered opener or row-click route selects `0x0b` or `0x0d`. So the
`LoadScreen.win` family now has a much cleaner shape: one outer message owner
`0x004e3a80`, one active-page render owner `0x004ea060`, and then the narrower page-specific
handlers and renderers beneath them. The launcher side is tighter now too: `0x004e4ee0` is the
shared open-or-focus ledger-page owner above this family. Outside sandbox it either re-enters
`shell_load_screen_select_page_subject_and_refresh` on the live runtime at `0x006d10a8` or
allocates that transient runtime, seeds it through `0x004e4b10`, and enters the visible modal
loop; inside sandbox it raises localized id `3899` `The ledger is not available in sandbox mode.`
instead. That narrows the remaining `LoadScreen.win` gap again: `TRAIN DETAIL` and
`STATION DETAIL` now read as dormant title-table entries unless some still-unrecovered nonstandard
selector reaches them.
- Editor breadth: the broader map-editor page owner is now bounded through
`map_editor_panel_select_active_section` `0x004ce070` and
`map_editor_panel_dispatch_active_section_message` `0x004cf700`, which switch among the grounded
setup pages, `Cities/Regions`, `Territories`, the `Players` and `Player Pool` setup slices, the
now-grounded `Building Density` page, the locomotives-available and industry-availability pages,
the economic and special-condition pages, the `Port/Warehouse Cargos` page, and the later report
pages. The mid-editor ownership is materially clearer now too: the chairman-slot editor is the
`Players` page, the available-chairman editor is the `Player Pool` page, and the former unnamed
dual tri-state page now lines up with localized page text `997` `Building Density` plus help text
`1017` and the direct field captions `1642` `Starting Building Density Level:` and `1644`
`Building Density Growth:`. Both controls are now bounded as stored ordinal bytes `0/1/2` rather
than loose labels: the first three-choice control is the map-wide starting-density selector, with
its default middle state `1` matching the documented `100%` baseline from `1643`; the second is
the paired overall growth selector whose effects later appear in the city-growth side of the
simulation. `map_editor_city_region_panel_construct` and
`map_editor_city_region_panel_handle_message` own the city-or-region editing lane with rename and
copy-industry-data flows; `map_editor_territory_panel_construct` and
`map_editor_territory_panel_handle_message` own the territory rename and border-remap lane;
`map_editor_locomotive_availability_panel_construct` plus
`map_editor_locomotive_availability_panel_handle_message` now bound the locomotive policy page
over `0x006ada84`; `map_editor_industry_availability_panel_construct` plus
`map_editor_industry_availability_panel_handle_message` do the same for the industry candidate
pool at `0x0062b268`; and `map_editor_port_warehouse_cargo_panel_construct` plus
`map_editor_port_warehouse_cargo_panel_handle_message` now ground the recipe-book page that edits
port or warehouse cargo policies through twelve per-book state blocks at
`[0x006cec78+0x0fe7+index*0x4e1]`. Each book now has a shared maximum annual production float at
`book+0x3ed` and five fixed cargo-line entries starting at `book+0x3f1` with stride `0x30`; each
line is bounded as a mode dword, annual amount, a supplied-cargo token at `+0x08`, and a
demanded-cargo token at `+0x1c`. The constructor and handler now make those fields materially
tighter too: the row pair shown in `Supply Only` and `Production Demand->Supply` is the `+0x08`
supplied-cargo selector, the row pair shown in `Demand Only` and `Production Demand->Supply` is
the `+0x1c` demanded-cargo selector, and the single amount field at `+0x04` is labeled `Annual
Demand:` only in mode `1` but `Annual Supply:` in modes `2/3`. The stronger new runtime-side
result is now a full chain rather than only the importer:
`scenario_state_rebuild_port_warehouse_cargo_recipe_runtime_tables` first imports those same five
lines into one repeated array of identical `0xbc`-byte runtime descriptors with no row-index
special casing, and the candidate-side rebuild pass at
`structure_candidate_collection_rebuild_runtime_records_from_scenario_state` `0x00412d70` then
projects those descriptors into the live structure collection at `0x0062ba8c` before
`structure_candidate_rebuild_cargo_membership_and_scaled_rate_tables` `0x00411ee0` rebuilds the
per-cargo runtime summary tables. The player-facing line modes remain `Disabled`, `Demand Only`,
`Supply Only`, and `Production Demand->Supply`, and the fourth mode is tighter now too: current
wording around `1674`, `1675`, and `504` plus the downstream scaling path says it is the
production-line mode governed by the shared annual production cap, where the entered annual amount
stays on the supply side while the demanded side becomes the normalized input branch. The
candidate-side accumulator pass reinforces that split by applying the shared production cap only
to the supply-half runtime branch and bypassing that scaling on the normalized demand half. The
lower gameplay side is tighter now too: `structure_candidate_query_cargo_runtime_summary_channels`
`0x00412650` is the first grounded consumer beneath that rebuild chain, because it lazily rebuilds
four per-cargo summary banks and returns one direct-supply channel, one cap-normalized supply
channel, one demand or input channel, and one scaled production-output subrow channel for a
requested cargo id; the sibling helper `structure_candidate_supports_or_references_cargo_id`
`0x004129d0` then uses those same banks plus the cached cargo-membership arrays to answer whether
a live candidate materially references a cargo at all. One broader collection pass also now ties
the editor rule side back into runtime filtering:
`structure_candidate_collection_refresh_cargo_economy_filter_flags` `0x0041eac0` rebuilds
per-candidate flag `[candidate+0x56]` across the live structure collection, and current grounded
callers show it rerunning directly off the runtime cargo-economy latch at `[0x006cec74+0x25f]`,
which aligns this lane with the editor's `Disable Cargo Economy` special condition rather than
leaving it as a purely editor-owned recipe page. The first common live gate beneath that filter is
now bounded too: `structure_candidate_is_enabled_for_current_year` `0x0041e220` is the shared
year-and-filter check used by the collection refresh and later candidate-selection branches, while
`structure_candidate_rebuild_local_service_metrics` `0x0041e2b0` is a setup-side local service
scorer that already consumes the same enabled candidate records through world-grid sampling. One
steady-state world-side consumer is now grounded as well:
`placed_structure_rebuild_candidate_cargo_service_bitsets` `0x0042c690` walks linked placed
structures, filters live category-`2` candidates through
`structure_candidate_is_enabled_for_current_year`, and compacts the direct and scaled supply-side
channels from `0x00412960` and `0x004129a0` into per-cargo bitsets on the placed-structure record.
The next site-side owner layer is tighter now too:
`placed_structure_refresh_linked_candidate_flag4` `0x0042c8f0` refreshes the sibling state bit at
`[site+0x0e6]`, `placed_structure_refresh_candidate_service_state` `0x0042cdf0` ties that flag
refresh to the cargo-service bitset rebuild,
`placed_structure_rebuild_candidate_local_service_tables` `0x0042ce00` then performs the heavier
per-site candidate score rebuild over the aligned float and word tables at `[site+0x107]`,
`[site+0x02]`, and `[site+0x6c]`, and `placed_structure_refresh_local_service_score_bundle`
`0x0042d580` is now the local wrapper that chains that rebuild into the neighboring post-passes
before the world-grid owner continues. Those post-passes are tighter too:
`placed_structure_apply_route_linked_service_caps` `0x0042cc50` is the first route-backed cap pass
over the rebuilt local tables,
`placed_structure_redistribute_local_service_pressure_from_neighbors` `0x0042c1b0` is the
neighboring-site redistribution pass, and `placed_structure_clamp_candidate_service_age_table`
`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
`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:
`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:
`shell_station_detail_set_active_candidate_service_preview` `0x00504ae0` stores the active
`(station id, candidate id)` pair for the world-side preview scan,
`shell_station_detail_clear_active_candidate_service_preview` `0x00504a90` tears that pair back
down, `shell_station_detail_update_candidate_service_entry` `0x00504ba0` is the shell-side entry
updater above that preview pair, `shell_station_detail_format_candidate_local_service_summary`
`0x00504bea` uses `placed_structure_query_candidate_local_service_metrics` together with localized
ids `681`, `682`, and `2813` to build the visible candidate service text,
`shell_station_detail_build_to_from_haul_summary_widget` `0x00505150` now grounds the paired `To`
and `From` hauled-traffic strip widgets, `shell_station_detail_present_to_from_haul_stats_popup`
`0x00504770` owns their click-through annual and lifetime `hauled TO/FROM this station` popup,
`shell_station_detail_refresh_nearby_structure_jump_rows` `0x00505470` owns the five-row
nearby-structure jump lane, and `shell_station_detail_refresh_candidate_service_rows` `0x00505760`
is now the larger row-list owner that enumerates active candidate-service entries and wires
`shell_station_detail_update_candidate_service_entry` into the per-row click path.
`shell_station_list_format_freight_and_express_availability_summary` `0x00506e50` feeds the
station-list summary `%1 has %2 freight loads and %3 express loads available for hauling...`, and
the paired modifier helper `shell_station_list_handle_center_or_rename_action` `0x00506d50` owns
the visible Shift-center and Ctrl-rename row actions. The report side is clearer as well:
`0x004d3060` is the dedicated `Stats - Trees` constructor over `map_editor_tree_stats_report`,
`0x004d3080` is the actual `General Validation` constructor over
`map_editor_general_validation_report`, and the same page table also now grounds `Stats - Cargo`,
`Stats - City/Region`, `Stats - City Count`, `Event Variable Values`, and the neighboring
event-validation page. The remaining open editor edge is therefore mostly the deeper gameplay
meaning of those site-side service scores and flag bits, not page ownership.
- Station-detail overlay: the shell-side candidate preview pair now has a grounded world consumer
too. `world_render_station_candidate_service_map_overlay` at `0x0043f640` reads the active
`(station id, candidate id)` pair from `0x005ee4fc` and `0x005ee500`, scans the placed-structure
collection, and then splits the legend by candidate mode. When the active candidate carries a
nonzero route-style byte at `[candidate+0x46]`, the overlay uses the heavier helper
`placed_structure_query_candidate_directional_route_overlay_summary` at `0x0047e690` in both
directions between the preview station and each scanned site and formats the resulting directional
rows as `3874` `Coming To %1` and `3875` `Going From %1`. When that byte is zero, the same overlay
falls back to the direct local-service path through
`placed_structure_query_candidate_local_service_metrics` and formats the two legend rows instead
as `3876` `Current Supply @ < %1` and `3877` `Current Demand @ > %1`. Empty directional lanes
collapse to `3878` `--None--`, and one title lane falls back to literal `All`. Current disassembly
no longer supports treating `3872` `Already Connected by Another Company` or `3873` `Not
Connected` as direct overlay-body emits.
- Station-detail overlay, corrected boundary: the neighboring connection-state note pair now appears
to live in a city connection-bonus label formatter, not in `0x0043f640`. That formatter is now
bounded as `city_site_format_connection_bonus_status_label` at `0x004207d0`: it directly chooses
localized ids `3868` through `3873` after consulting the reusable city-peer scan
`city_connection_bonus_exists_matching_peer_site` at `0x00420030`. Separately, `3879` `Out of
Sync` is grounded under the multiplayer preview dataset path instead:
`multiplayer_preview_dataset_service_launch_state_and_warn_out_of_sync` at `0x0046b780` checks
global `0x006cd91c`, raises the `Out of Sync` shell status through `0x5386e0`, and then continues
through the wider multiplayer preview launch-state service. So the station-detail overlay
currently owns only the `Coming To`, `Going From`, `Current Supply`, `Current Demand`, `--None--`,
and `All` legend lanes.
- Station-detail overlay, ownership side: one reusable site helper is grounded now too.
`placed_structure_query_linked_company_id` at `0x0047efe0` resolves the current placed structure's
linked instance through `0x0062b26c` and returns its company id from `[instance+0x276]`; the
adjacent city bonus formatter at `0x004207d0` compares that id against the active company selector
before choosing whether a scanned site should carry `3871` `Connected By Another Company` or
`3872` `Already Connected by Another Company`. The larger caller boundary is no longer open
either: the first bounded announcement owner above this formatter family is now
`company_evaluate_and_publish_city_connection_bonus_news` at `0x00406050`, which re-enters the
peer-route candidate builder at `0x004046a0` and later publishes one of the localized
city-connection bonus news strings `2888`, `2890`, or `2921` through the shell news path.
- Station-detail overlay, peer-selector side: the city bonus formatter no longer depends only on
boolean peer existence. The companion helper
`city_connection_bonus_select_first_matching_peer_site` at `0x00420280` is now grounded as the
first-match selector paired with `city_connection_bonus_exists_matching_peer_site`: it walks the
same city-peer candidate set, applies the same site-class table plus the narrower
station-or-transit and linked-instance class-byte flags, and returns one representative matching
peer site id instead of a boolean. `city_site_format_connection_bonus_status_label` reuses that
selector after the note checks so it can recover one linked company context from the selected
peer. The remaining open edge here is therefore above this formatter family, not inside the
peer-scan pair itself.
- Station-detail overlay, caller side: the reusable bridge between the status formatter and the
company news lane is now bounded too. `city_connection_bonus_build_peer_route_candidate` at
`0x004046a0` reuses `city_connection_bonus_select_first_matching_peer_site` with both selector
flags forced on, samples the selected peer's derived coordinates through `0x0047df30` and
`0x0047df50`, and then either tries the shared heavy builder
`city_connection_try_build_route_with_optional_direct_site_placement` `0x00402cb0` or falls
back to the smaller wrapper `city_connection_bonus_try_compact_route_builder_from_region_entry`
`0x00404640` before handing the result back to the company-side announcement sweep at
`0x00406050`. The score side of that announcement lane is tighter now as well:
`city_compute_connection_bonus_candidate_weight` at `0x004010f0` provides the per-city opportunity
weight, `company_query_min_linked_site_distance_to_xy` at `0x00405920` provides the nearest
linked-site distance term, `company_count_linked_transit_sites` at `0x00426590` provides one of
the company-side caps, `company_compute_connection_bonus_value_ladder` at `0x00425320` supplies
the bounded company-side value scalar, and
`company_compute_prime_rate_from_issue39_scenario_baseline` at `0x00424580` now bounds the
shared prime-rate-side helper that this lane reuses beside the raw issue-`0x39` total,
`scenario_state_sum_issue_opinion_terms_raw` at `0x00436710` now bounds the raw additive
issue-total helper beneath that term, and `company_connection_bonus_lane_is_unlocked` at
`0x00427590` is the small boolean gate above the ladder. Wider governance and CompanyDetail xrefs
now tighten slot `0x2b` into the rolling net-profits lane reused by annual finance checks and a
per-share/history formatter, while the report-history descriptor table now aligns raw slot `0x09`
with the Income Statement fuel-cost lane surfaced by tooltip `1309`. The wider result now reads
more like recent net profits minus recent fuel burden than a governance-pressure term. That now
also sharpens the annual finance lane at `0x00401c50`: the first bankruptcy branch reads as
sustained cash-and-debt stress over recent profits and fuel burden, the later fallback branch as
a deeper `-300000` cash / three bad years cleanup trigger, and the later stock-issue branch reads
as a price-to-book-versus-coupon approval ladder rather than a generic support vote. The tail is
cleaner now too: it compares total retired versus newly issued principal to choose the `2882..2886`
debt headline family, then publishes `2887` separately from the accumulated repurchased-share
count. The sibling news owner above the same
city-pair route family is bounded now too:
`simulation_try_select_and_publish_company_start_or_city_connection_news` `0x00404ce0`
filters and scores candidate city entries, re-enters the same shared heavy builder through
`city_connection_try_build_route_between_region_entry_pair` `0x00404c60` for the dense pair
sweep and the final retry, and then publishes `2889` `%1 has started a new company - the %2`
or `2890` `%1 has connected %2 to %3.` through the shell news path. The remaining open edge on
this branch is therefore narrower now: it is mostly whether `0x39` should be read as the
narrower city-connection public-opinion lane or as part of a broader management-attitude family,
not the ownership of the connection-bonus formatter, peer-route candidate path, or company news
gate.
- Station-detail overlay, route-list side: the neighboring helper
`placed_structure_append_unique_route_entry` at `0x0047f010` is now grounded as the
append-if-missing builder for the six-byte route-entry list rooted at `[site+0x462]` and
`[site+0x466]`. That matters here because the directional overlay query at `0x0047e690` consumes
the same list, so the remaining uncertainty is no longer list ownership. It is down to the exact
semantics of each entry's `u32` payload.
## Next Mapping Passes
- Resolve the owner-side callback roles behind the validated GameSpy packet branches, especially
`[route+0x9c]`, `[route+0xa0]`, `[route+0xa4]`, and `[route+0xd4]`.
- Determine whether any later world-mode branch beneath the frame owner bypasses the shell
controller input path for non-cursor gameplay input, since the current grounded overlay and cursor
helpers still reuse `0x006d4018`.
- Keep detailed pending-template or transport work scoped to the specific atlas edges that remain
unresolved.