rrt/docs/control-loop-atlas.md

151 KiB
Raw Blame 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.

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 request id plus companion value, 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 sample through multiplayer_transport_enqueue_callback_slot24_record. So the publication boundary is explicit and the request-id ownership is explicit, even though the exact user-facing meaning of the sample and the companion value at [entry+0x54] is still open. 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 marker text from [entry+0x50] through multiplayer_transport_format_selector_view_probe_marker, formats one PNG %s %d line around that marker and the entry-local selector-view 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 route-mode state machine now looks consistent with that: current grounded mode transitions 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]. 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 public-support helper company_compute_public_support_vote_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, 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 repartition adjacent route-entry tracker groups around the refreshed anchor, rewrite compatible endpoint slots through 0x004950f0, and refresh 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 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 the route-side sweep through 0x004a6630. 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, rolls candidate-local service metrics and peer-route deltas back into three per-site cache floats at +0x0e, +0x12, and +0x16, and 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. Current grounded evidence says that pass prunes or upgrades older company-owned trains, then 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 slots 0x2b and 0x2c, chooses one negative pressure ladder -600000 / -1100000 / -1600000 / -2000000 from the current slot-0x2c bands around 120000 / 230000 / 340000, requires public support at least 15 or 20 depending on whether all three sampled years failed, checks 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-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 bounded first threshold layer: 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 1000-share batch with floor 2000, requires public support at least 22, requires the support times batch product to clear 55000, and then uses a piecewise approval ladder 0.07/1.3 -> 0.14/0.35 before the share-issue path proceeds. 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 slot 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 remaining gaps on this lane are therefore narrower than before: 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 capital or dividend summary block through shell_company_detail_render_capital_and_dividend_summary_panel, control 0x948a now grounds the per-share metrics block through shell_company_detail_render_per_share_metrics_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 public-support side is now tighter too because company_compute_cached_recent_performance_support_score and company_compute_public_support_vote_scalar bound the recent-performance and public-support 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, company_compute_issue39_opinion_bias_scalar at 0x00424580 contributes one smaller issue-0x39 opinion term, 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 a rolling shareholder-facing performance lane reused by annual shareholder-revolt or creditor-pressure checks and a per-share/history formatter, while 0x09 remains the narrower current governance-pressure term read after those broader gates. The wider 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.