rrt/docs/control-loop-atlas.md

340 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.

Subsystem notes now live under docs/atlas for faster navigation. The longform atlas remains the canonical narrative reference during this transition.

CRT and Process Startup

  • Roots: entry at 0x005a313b, CRT helpers in the 0x005a2d..0x005ad4.. range, and app_bootstrap_main at 0x00484440.
  • Trigger/Cadence: single process startup path before shell or engine services exist.
  • Key Dispatchers: startup_init_tls_state, startup_init_file_handle_table, startup_run_init_callback_table, __setenvp, startup_build_argv, ___crtGetEnvironmentStringsA, then app_bootstrap_main.
  • State Anchors: CRT heap and file-handle tables; process environment and argv storage.
  • Subsystem Handoffs: exits the generic CRT path at app_bootstrap_main, which becomes the first RT3-owned coordinator.
  • Evidence: artifacts/exports/rt3-1.06/startup-call-chain.md, artifacts/exports/rt3-1.06/function-map.csv.
  • Open Questions: exact ownership boundary between compiler CRT shims and the first game-owned bootstrap helper; whether any nontrivial startup callbacks seed game globals before app_bootstrap_main.

Bootstrap and Shell Service Bring-Up

  • Roots: app_bootstrap_main at 0x00484440, bootstrap_init_shell_window_services at 0x004840e0, and shell_install_global_controller at 0x0051ff90.
  • Trigger/Cadence: one-time bootstrap handoff immediately after CRT completion.
  • Key Dispatchers: app_bootstrap_main, bootstrap_init_shell_window_services, shell_install_global_controller, shell_service_pump_iteration, graphics config load or default-init helpers, runtime capability probes, and early shell service initializers under the 0x004610..0x0053f0.. branch.
  • State Anchors: global shell controller pointer 0x006d4024, sibling display/runtime globals under 0x006d402c and 0x006d4030, and host capability flags gathered by bootstrap_probe_system_profile.
  • Subsystem Handoffs: after the global shell controller has been installed the bootstrap path enters the repeating shell_service_pump_iteration loop, which services shell-state work and hands each iteration down into the controller frame path; when the shell lifetime ends this same bootstrap path tears the shell bundle down and returns to app_bootstrap_main.
  • Evidence: startup-call-chain.md, function-map rows for app_bootstrap_main, bootstrap_init_shell_window_services, shell_install_global_controller, shell_service_pump_iteration, shell_load_graphics_config_or_init_defaults, shell_reset_display_runtime_defaults, and related graphics setup helpers.
  • Open Questions: whether gameplay or in-engine world stepping later escapes this bootstrap-owned shell loop entirely, or whether gameplay entry still rendezvous with the same outer coordinator before the shell bundle is destroyed.

Shell UI Command and Deferred Work Flow

  • Roots: shell callback paths that converge on shell_dispatch_ui_command at 0x00464410.
  • Trigger/Cadence: event-driven UI command dispatch plus deferred-message queue flushing during shell activity.
  • Key Dispatchers: shell_dispatch_ui_command, shell_enqueue_deferred_work_message, shell_post_deferred_message_type5, shell_post_deferred_message_type6, shell_enqueue_deferred_message_type4, shell_enqueue_deferred_message_type1.
  • State Anchors: shell object at 0x0062be68, queue roots around [this+0x11369d], [this+0x1136a1], and [this+0x1136a5], global routing gates at 0x006d4034, and the separate detail-panel controller rooted at 0x006d0818.
  • Subsystem Handoffs: routes into graphics config, scenario-text export, overlay generation, multiplayer UI, shell detail windows such as EditorPanel.win and TrainDetail.win, and presentation-facing deferred work later drained by shell_service_frame_cycle.
  • Evidence: function-map shell rows around 0x00464410, 0x004d4500, 0x004ddbd0, and 0x0051f1d0..0x0051f460.
  • Open Questions: whether the shell command dispatcher is also used by hotkeys or only by UI callback tables; the current 0x006d0818 detail-panel path looks shell-only and does not yet explain gameplay world entry.

Presentation, Overlay, and Frame Timing

  • Roots: the bootstrap-owned shell_service_pump_iteration at 0x00483f70, the shell-state service pass shell_state_service_active_mode_frame at 0x00482160, the installed global shell controller at 0x006d4024, the pending frame-cycle owner shell_service_frame_cycle at 0x00520620, and the frame-time history path under shell_update_frame_time_history at 0x0051fd70.
  • Trigger/Cadence: recurring bootstrap-owned shell service work once the active mode, controller window, and display runtime are live; special modal or content-building paths can also force immediate frame servicing inside that broader cadence.
  • Key Dispatchers: shell_service_pump_iteration, shell_state_service_active_mode_frame, shell_service_frame_cycle, shell_refresh_presentation_frame, shell_update_frame_time_history, shell_get_smoothed_frame_scalar, shell_set_gamma_ramp_scalar, and overlay builders such as shell_queue_single_world_anchor_overlay, shell_queue_world_anchor_overlay_list, and shell_queue_indexed_world_anchor_marker.
  • State Anchors: shell state at 0x006cec74, active mode pointer 0x006cec78, shell frame history ring at 0x006d403c, display/runtime state inside the controller block near [this+0x114282] and [this+0x11428a], presentation service pointer at [this+0x0c], and the native controller window handle at [this+0x00].
  • Subsystem Handoffs: the bootstrap-owned pump runs shell-bundle polling and shell-state maintenance before the shell-state pass synchronizes active-mode helpers and modal-status work and dispatches the controller frame cycle, which then consumes world/object state for overlays and presentation refresh, uses the controller window handle for one-time ShowWindow and related UI interaction, and drains the deferred work queues at the end of the cycle.
  • Evidence: function-map rows for shell_service_pump_iteration, shell_state_service_active_mode_frame, shell_service_frame_cycle, shell_flush_deferred_work_queues, frame history, gamma ramp, world-anchor overlay builders, and graphics runtime helpers.
  • Open Questions: how simulation cadence rendezvous with the shell presentation cadence once gameplay takes over and whether gameplay stepping exits this shell-owned controller path entirely.

Map and Scenario Content Load

  • Roots: shell_map_file_entry_coordinator at 0x00445ac0, the larger active-mode profile owner shell_active_mode_run_profile_startup_and_load_dispatch at 0x00438890, the shell-mode switcher shell_transition_mode at 0x00482ec0, the first grounded world-entry branch world_entry_transition_and_runtime_bringup at 0x00443a50, shell_map_file_world_bundle_coordinator at 0x00445de0, reference-database setup via map_bundle_open_reference_databases at 0x00444dd0, and narrower loaders such as map_load_geographic_label_database and map_load_city_database.
  • Trigger/Cadence: shell tutorial launch, editor or detail-panel file actions through fileopt.win, map-scenario open paths, and scenario-text export batch commands.
  • Key Dispatchers: shell_map_file_entry_coordinator, shell_active_mode_run_profile_startup_and_load_dispatch, shell_transition_mode, world_entry_transition_and_runtime_bringup, world_runtime_release_global_services, shell_map_file_world_bundle_coordinator, map_bundle_open_reference_databases, map_load_geographic_label_database, map_load_city_database, scenario_text_export_build_language_file, scenario_text_export_report_language_file, scenario_text_export_batch_process_maps.
  • 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. The shell-side mode owner above those file coordinators is clearer now too. shell_transition_mode no longer reads like a generic mode switch: its ABI is now grounded as a thiscall with two stack arguments because the body reads the requested mode from [esp+0x0c] and returns with ret 8. The grounded world-entry load-screen call shape is (4, 0), not a one-arg mode switch. The second stack argument is now tighter too: current local evidence reads it as an old-active-mode teardown flag, because the 0x482fc6..0x482fff branch only runs when it is nonzero and then releases the prior active-mode world through 0x434300, 0x433730, and the common free path before clearing 0x006cec78. The later world-entry reactivation branch correspondingly uses (1, esi) rather than (1, 0). The current live hook probes now push the remaining auto-load gap much later too: on the hook-driven path shell_transition_mode(4, 0) returns cleanly, and the full old-mode teardown stack under 0x5389c0 now returns too, including 0x5400c0, the 0x53fe00 -> 0x53f860 remove-node sweep over [object+0x74], and the nearby mode-2 teardown helper 0x00502720. The same live run now also reaches and returns from shell_load_screen_window_construct 0x004ea620 and the immediate shell publish through 0x00538e50. Its constructor jump table is tighter now too: mode 1 is not the direct Game.win constructor, but the startup-dispatch arm rooted at 0x483012; mode 2 enters Setup.win, mode 3 enters Video.win, mode 4 enters the plain LoadScreen.win branch at 0x4832e5, mode 5 enters Multiplayer.win, mode 6 enters Credits.win, and mode 7 enters Campaign.win. The important static correction is that the startup-runtime slice 0x004ea710 -> 0x0053b070(0x46c40) -> 0x004336d0 -> 0x00438890 belongs to mode 1, not mode 4. Mode 4 only constructs and publishes the LoadScreen.win object through 0x004ea620 and 0x00538e50. The older hook-driven (4, 0) path therefore was not mysteriously skipping the startup-runtime object; it was entering the wrong jump-table arm for that work. The caller split above that owner is tighter now too: world_entry_transition_and_runtime_bringup reaches the same owner at 0x443b57 with (0, 0) after dismissing the current shell detail panel and servicing 0x4834e0(0, 0), while the saved-runtime path at 0x446d7f does the same before immediately building the .smp bundle payloads through 0x530c80/0x531150/0x531360. That makes the LoadScreen.win startup lane the only currently grounded caller that enters 0x438890 with (1, 0) instead of (0, 0). The remaining runtime uncertainty is narrower now too: the plain-run logs still show the plain LoadScreen.win state under (4, 0), and the corrected allocator-window run now reinforces the same read because the post-construct allocator stream stays empty instead of showing the expected 0x46c40 startup-runtime allocation. The first lower allocator probe on 0x005a125d was not trustworthy because that shared cdecl body sits behind the thunk and the initial hook used the wrong entry shape, and the first direct thunk hook was also not trustworthy because a copied relative-jmp thunk cannot be replayed through an ordinary trampoline. But the later corrected thunk run plus the jump-table decode now agree: the next meaningful hook-driven test is mode 1, not mode 4. mode_id = 2, and it never advanced into ready gate passed, staging, or transition. So that run did not actually exercise the 0x0053b070 -> 0x004336d0 -> 0x00438890 subchain at all. The next runtime pass now lowers the ready-poll defaults to 1 and 0 and adds an explicit ready-count log so the mode-4 startup lane either stages immediately or shows exactly how far the gate gets. That adjustment worked on the next run: the hook now stages and completes the shell_transition_mode path again, with LoadScreen.win construction and publish returning cleanly. But the post-publish startup subchain is still unresolved: there is still no trusted 0x46c40 allocator hit, no direct 0x004336d0 entry, and no direct 0x00438890 entry. So the next clean runtime boundary is the tiny LoadScreen.win scalar setter at 0x004ea710, which sits immediately before the 0x0053b070 allocation in the static mode-4 branch. The immediate next runtime check is even more concrete than the helper hook, though: inspect the state that 0x004ea710 should leave behind. The hook now logs the post-transition LoadScreen.win singleton, its field [+0x78], 0x006cec78, the shell state's [+0x0c] active-mode object field, and the startup selector. If 0x004ea710 really ran on the mode-4 branch, [LoadScreen.win+0x78] should no longer be zero after shell_transition_mode returns. The latest run answered that directly: after transition return, field_active_mode_object is still the LoadScreen.win singleton, 0x006cec78 is still null, [LoadScreen.win+0x78] is still zero, and the startup selector is still 3. So the current best read is that RT3 is still parked in the plain LoadScreen.win state at transition return rather than having entered the separate runtime-object path yet. That shifts the best next runtime boundary from “deeper inside shell_transition_mode” to “what later active-mode service tick, if any, promotes the load-screen object into the startup-dispatch path.” The next run now logs the first few shell-state service ticks after auto-load is attempted with that same state tuple (0x006cec78, [shell_state+0x0c], 0x006d10b0, [LoadScreen.win+0x78], selector), so the next question is very narrow: does one later service tick finally promote the plain LoadScreen.win state into the startup-runtime object path, or does it stay frozen as-is? The internal selector split in 0x438890 is tighter now too: [0x006cec7c+0x01] is a separate seven-way startup selector, not the shell mode id. Values 1 and 7 load Tutorial_2.gmp and Tutorial_1.gmp, values 3/5/6 collapse into the same profile-seeded file-load lane through 0x445ac0([0x006cec7c]+0x11, 4, &out_success), value 2 is a world-root initialization lane that allocates 0x0062c120 and then forces selector 3, and value 4 is the setup-side world reset or regeneration lane that rebuilds 0x0062c120 from 0x006d14cc/0x006d14d0 before later world setup continues. The write side is tighter now too: Campaign.win writes selector 6, Multiplayer.win writes selector 3 on one pending-status path, and the larger Setup.win dispatcher writes selectors 2, 3, 4, and 5 on its validated launch branches. That makes the file-load subfamily read less like one generic save-open branch and more like a shared profile-file lane reused by setup, multiplayer, and campaign owners. The world-entry owner boundary is tighter now too: world_entry_transition_and_runtime_bringup at 0x00443a50 no longer stops at the initial shell transition and world allocation head. The same grounded function continues through the larger post-load generation tail up to 0x00444dc2, which means the later Setting up Players and Companies... and neighboring post-load passes are not floating raw callsites after all. That same owner now clearly covers the event-runtime refresh through 0x433130, chairman-profile materialization through 0x437220, neighboring route and tracker refresh families, and the one-shot kind-8 runtime-effect service through 0x432f40 before clearing shell-profile latch [0x006cec7c+0x97]. The Setup.win dispatcher is less opaque now too: the early 0x0bc1..0x0c24 family is mostly fixed submode selection above 0x00502c00, except for the separate 0x0bc2/0x0bc5/0x0bc6/0x0bc7 shell-open quartet above 0x00501f20; 0x0c1f is the settings-window escape; 0x0c1e/0x0c20/0x0c22 are direct shell requests into 0x00482150; the fixed submode buttons now have concrete lower targets such as 0x0bc1/0x0bc8 -> 15, 0x0bc3 -> 16, 0x0bc4 -> 1, 0x0c80 -> 13, 0x0c1c -> 17, 0x0c1d -> 2, 0x0c24 -> 14, 0x0c81 -> 14, 0x0c82 -> 6, 0x0c83 -> 10, and 0x0c84 -> 12; the 0x0ce6/0x0ce7/0x0d49/0x0d4a/0x0e82/0x0e83 branches are bounded list or slider adjustments on staged setup fields; and the later 0x0dca/0x0dcb/0x0de9/0x0df3/0x0e81/0x0f6f/0x0f70 controls are the explicit selector-writing launch buttons rather than one anonymous validated-launch blob. The constructor-side callbacks are tighter too: control 0x0ce8 is a table-driven payload-label draw callback above 0x00502030, not another launch root, and controls 0x0e86 and 0x0e87 do not select more setup roots; they update the persisted shell-state selector pairs at [0x006cec74+0x233/+0x237] and [0x006cec74+0x23b/+0x23f] through 0x00502160 and 0x005021c0, then immediately save config through 0x00484910(1). The constructor body is tighter too: it seeds the initial Setup.win state by running 0x502910, 0x502550, and 0x502c00(1) before the user interacts with the window, installs 0x0c80..0x0c86 and 0x0f6f..0x0f71 as homogeneous button bands, and treats 0x0e88 as one separate special control with retuned float fields rather than another ordinary launch root. The remaining optional constructor child 0x0bd0 is tighter now too: it is built from a separate template block and optional owned heap object before registration, not another hidden setup-root button. The generic shell helper layer beneath that constructor is tighter now too: 0x53fa50 is the shared resource-bind and child-list initialization helper, 0x53f830 is the child-control lookup-by-id helper over the intrusive list at [this+0x70], 0x558130 is the child-control finalizer that stamps the owner pointer and resolves localized captions before the control goes live, and 0x53f9c0 is the ordered child-control registration helper used by the optional 0x0bd0 branch and other shell dialogs. The submode selector itself is tighter now too because its button-state lane is mostly decoded: 0xbc5 tracks submode 15, 0xbc6 tracks 16, 0xbba tracks 2, 0xbbb tracks 3, 0xbc3 tracks 13, 0xbbc groups 3/4/5, 0xbbd tracks 4, 0xbbe tracks 5, 0xbbf groups 6/12/14, 0xbc0 tracks 7, 0xbc1 tracks 8, 0xbc2 tracks 9, 0xe75 tracks 10, and 0xf6e tracks 17. RT3.lng and the setup art families now also make several of those top-level roots read less like anonymous ids and more like real menu panels: submode 1 is the strongest current landing-panel fit, 2 is the Single Player root, 7/8/9 are the Editor / New Map / Load Map family, 15 is Extras, and 17 is Tutorial. By elimination against the separate shell Credits.win mode, the remaining top-level Setup.win roots now most safely read as 13 = Multi Player and 16 = High Scores. The file-backed side is tighter too: 0x502c00 now maps submodes exactly as 4 -> dataset 5, 9 -> 4, 6 -> 8, 10 -> 6, 12 -> 10, and 14 -> 9, so the saved-game-backed family is no longer one blurred list pane but a small set of stable dataset variants above 0x4333f0/0x4336a0. The file-list builder under that pair is tighter too: 0x4333f0 no longer just emits unsorted 0x25a-byte rows with raw names at +0x0 and normalized labels at +0x12d. After the scan it now clearly re-enters 0x51dc60, which is a generic adjacent-swap insertion sort over fixed records; in this setup-side caller it receives record_size = 0x25a and key_offset = 0x12d, so the resulting Setup.win rows are sorted by display label rather than by the raw filename. The file-backed header split is tighter too: 0x5027b0 now maps the top header-control ids as 4 -> 0xd4b, 9 -> 0xde8, 6/12/14 -> 0xdf2, and 10 -> 0xe85. RT3.lng closes one earlier mistake here: those values are local setup control or resource ids, not localized text ids. The setup art bundle now tightens that family split one step further too: under rt3_2WIN.PK4 the distinct file-backed setup art families are the shared Setup_Load lane and the separate Setup_Sandbox lane, which matches the selector-side evidence that mode 10 is the sandbox-backed new list while mode 12 is its load sibling. Combined with the builder at 0x4333f0, that shows only submodes 4 and 10 using the alternate localized-stem list-label path; 6, 9, 12, and 14 keep the direct filename-normalization lane. The rt3_2WIN.PK4 extraction path is grounded a bit more cleanly now too: current pack4 samples use a shared 0x03eb header, a fixed 0x4a-byte directory entry stride, and a payload base at 8 + entry_count * 0x4a. In the checked UI bundle the entry table is contiguous and Campaign.win extracts cleanly at directory index 3 with payload length 0x306a. The extracted .win payload family now has one narrow shared shape too: Campaign.win, CompanyDetail.win, and setup.win all share the same first 0x50 bytes at offsets 0x00, 0x0c, 0x10, 0x14, 0x34, 0x38, 0x40, and 0x48, while CompanyDetail.win and setup.win also carry an inline root .imb name immediately at 0x51. Current resource scans show Campaign.win embedding the litCamp*/Ribbon* family, CompanyDetail.win embedding mainly CompanyDetail.imb, GameWindow.imb, and Portrait.imb, and setup.win embedding the broader Setup_Background/Buttons/New_Game/Load/Sandbox art families. The control records between those strings are still undecoded, but the resource-record shell itself is tighter now: all checked .win samples use the same three-word prelude prefix 0x0bb8, 0x0, 0x0bb9, and the fourth prelude word matches resource_name_len + 1. The next word after the terminating NUL then behaves like a per-record selector lane. In setup.win the dominant Setup_Buttons.imb family alternates between 0x00040000 and the incrementing 0x00010c1c..0x00010c86 series with dominant inter-record strides 0xb7/0xdb; in Campaign.win the litCamp*/Ribbon* family carries the incrementing 0x0004c372..0x0004c38e selector block with dominant 0x158/0x159 and 0xb2/0xb3 strides. That campaign lane is now directly aligned to the executable-side control ids too: the low 16 bits of litCamp1..16 map exactly to 0xc372..0xc381, and the low 16 bits of Ribbon1..16 map exactly to 0xc382..0xc391, matching the Campaign.win progress and selector control bases already grounded from RT3.exe. The fuller selector export now tightens the auxiliary families too: litArrows.imb covers 0xc36c..0xc371 exactly and litExits.imb covers 0xc397..0xc39a exactly, matching the constructor-side six-control arrow strip and four-control exit strip. The second post-name dword is tighter now too: its middle 16-bit lane groups those same Campaign.win records under 0xc368, 0xc369, 0xc36a, and 0xc36b, which matches the four page-strip controls and cleanly buckets the first five campaign entries, the next five, the next three, and the final three under the same page families. There are still no .imb selector records for 0xc393..0xc396 or 0xc39b, which makes those message-side page-write controls look more like structural buttons than art-backed repeated resource records. The grouped 3/4/5 family is narrower now too: 0x0ce5 is no longer part of it, because that control writes selector 3 and then selects submode 9 as the Load Map sibling. The nearby 0x0dcb branch instead conditionally selects submode 5 or 3, which keeps 3 as the strongest current New Game / Options companion and 5 as the strongest current Sandbox companion. The file-backed single-player side is tighter in the same way now: modes 4 and 10 are the only siblings using the alternate localized-stem row-label path, so they now read most safely as the two setup-local template or profile list variants rather than ordinary save lists. Mode 10 is the stronger one of the pair because neighboring validated launch control 0x0e81 both routes into selector 5 and sets sandbox byte [0x006cec7c+0x82] = 1, which makes it the strongest current fit for the setup-local New Sandbox list. The distinct Setup_Sandbox art family in rt3_2WIN.PK4 now reinforces that same split one step further, which makes mode 12 the strongest closed fit for the paired Load Sandbox lane; mode 4 is therefore the strongest remaining non-sandbox peer in that same pair and now most safely reads as the setup-local New Scenario-style chooser. Modes 6, 12, and 14 now tighten one step further as the three selector-3 direct-filename setup-local load siblings because they stay on the direct filename-normalization lane, share the same 0xdf2 header family, and clear the same presence-style latch [0x006cec7c+0x97]; mode 14 is the strongest current landing panel for that cluster because 0x0c24 jumps to it directly while 0x0c82 and 0x0c84 only reach the sibling modes 6 and 12 from inside the same load family. Current control-pairing and setup-art evidence now make 12 = Load Sandbox the strongest closed per-submode assignment. The remaining non-sandbox pair is closed now too: the deeper bundle filter at 0x433260 distinguishes dataset 9 from dataset 8 by one extra nonzero payload-flag family, and the editor-side metadata path now grounds [0x006cec78+0x66de] as the direct Campaign Scenario checkbox bit because editorDetail.win ties control 0x5b6e to localized ids 3160/3161. That makes dataset 9 the campaign-designated load family and dataset 8 the ordinary scenario load family, so 14 = Load Campaign and 6 = Load Scenario now read as grounded rather than residual. 0x502910 is tighter in a corrective way too: it is not a mode-3-only helper after all, but the shared non-file-backed payload panel that formats 0xcf3/0xcf4/0xcf5/0xd4f, mirrors option byte [0x006cec7c+0x7d] into 0x0ce9..0x0ced, rebuilds row host 0x0ce8 from payload bytes [+0x31b/+0x31c], and mirrors live row markers into [0x006cec7c+0x87]. That makes mode 3 just one user of the shared payload-driven panel, not the sole owner of it. The payload-helper cluster under that panel is tighter now too: 0x502220 does not just republish labels and the preview surface. It first re-enters shell_setup_load_selected_profile_bundle_into_payload_record 0x442400, which clears one full 0x100f2-byte setup payload record, builds a rooted path from the staged profile stem, opens the selected bundle through 0x530c80, and then reads either the ordinary saved-profile chunk family or the map-style chunk family through 0x531150/0x531360 depending on the selected extension shape. Only after that does 0x502220 copy payload fields +0x14/+0x3b2/+0x3ba/+0x20 into the staged runtime profile through 0x47be50, which in turn normalizes the payload category bytes at [payload+0x31a + row*9] and the local marker-slot bytes at [payload+0x2c9..] through 0x47bc80. The copied-field consumer split is tighter now too: payload +0x14 becomes staged profile [0x006cec7c+0x77], which is the visible setup scalar later formatted into controls 0x0e84 and 0x0d4f and adjusted by the 0x0d49/0x0d4a pair; payload +0x3b2 becomes [0x006cec7c+0x79], the live-row threshold that the payload-row draw callback uses to choose style slot 0x18 versus 0x19; and payload +0x3ba becomes [0x006cec7c+0x7b], the current scroll or row-index lane adjusted by the 0x0ce6/0x0ce7 pair. So the known setup-side payload consumers still stop well before the later candidate table, but the early copied lanes are no longer anonymous. The adjacent region-side worker family is tighter in a negative way too: the setup payload path now gives one useful upper bound on the newer candidate-availability source block too. The map-style setup loader is definitely pulling chunk families 0x0004/0x2ee0/0x2ee1 into one large 0x100f2-byte payload record, and the fixed 0x6a70..0x73c0 candidate table clearly lives inside the same broad file family; but the grounded setup-side consumers we can actually name after that load still only touch earlier payload offsets such as +0x14, +0x20, +0x2c9, +0x31a, +0x3ae, +0x3b2, and +0x3ba. So the current evidence is strong enough to say the candidate table is probably housed inside the setup payload family, but not yet strong enough to name one setup-side consumer that reads the 0x6a70 header or the fixed-width entries directly. The newer fixed-offset compare pass tightens that lower setup slice too: across the checked map/save pairs Alternate USA.gmp -> Autosave.gms, Southern Pacific.gmp -> p.gms, and Spanish Mainline.gmp -> g.gms, the known setup payload lanes +0x14 and +0x3b2 are preserved map-to-save on the same scenario-family split as the later candidate-table headers (0x0771/0x0001, 0x0746/0x0006, 0x0754/0x0001), while +0x3ae stays fixed at 0x0186 and +0x3ba stays fixed at 1 across all six files. By contrast, +0x20 does not survive as one shared source value (0xd3 -> 0xb4, 0x6f -> 0x65, 0xe3 -> 0x78 across those same pairs). So the current best read is that the setup payload mixes preserved scenario metadata and later save-variant state well before the 0x6a70 candidate table, rather than acting as one uniformly copied prelude. The adjacent region-side worker family is tighter in a negative way too: the setup payload loader is now clearly separate from the broader region-building and placement cluster around 0x422320..0x423d30, whose current grounded helpers now include 0x422320, 0x4228b0, 0x422900, 0x422a70, 0x422be0, 0x422ee0, 0x4234e0, 0x4235c0, and world_region_refresh_cached_category_totals_and_weight_slots 0x423d30 rather than one hidden setup-only panel. The leading region helper is no longer unnamed either: 0x422320 is now bounded as the recurring cached-structure-scalar normalization pass that writes [region+0x2e2/+0x2e6/+0x2ea/+0x2ee], while 0x422a70 is the shared placement-validation and commit gate beneath both the per-region worker and one second world-side placement loop. The neighboring 0x4234e0 accessor is tighter too: it is the shared projected structure-count scalar query by category that later feeds both the per-region placement family and the map-editor city count stats report. So the remaining gap is no longer “what are these setup payload helpers doing,” but only how aggressive we want to be when naming the last top-level setup roots from mostly RT3.lng and asset-side evidence. The adjacent summary helper is tighter too: 0x502550 is not another hidden submode owner. It republishes the staged path tail in 0xe7f, the scalar summary in 0xe84, the two persisted selector lists in 0xe86/0xe87, and the config toggles in 0xe88/0xe89/0xe8a. The remaining top-level gap is cleaner now too: submode 16 still has no distinct downstream helper or launch branch in the local selector/refresh family, but it is no longer a blank bucket. Current evidence now bounds it as the 0x0bc3 -> 16 top-level button whose visual-state lane is surfaced through control 0xbc6, and the strongest residual fit is High Scores because Credits already lives in separate shell mode 6. The validated launch lane is tighter now too: it no longer just writes selector 3 or 5 as one undifferentiated blob, and it no longer includes 0x0ce5 or 0x0dcb. 0x0ce5 is the Load Map selector because it writes selector 3 and then selects submode 9, while 0x0dcb is the later conditional 5/3 companion-selector sibling rather than a file launch. The actual validated staged-profile lane is now bounded more narrowly: 0x0cf6 and 0x0e81 are the selector-5 siblings, while the neighboring selector-3 validated lane is at least shared by 0x0de9 and 0x0df3; the shared bridge at 0x4425d0 then forces [0x006cec7c+0xc5] = 1, mirrors payload bytes into [profile+0xc4], [profile+0x7d], and [profile+0xc6..+0xd5], and only then issues shell request 0x0cc. The file-side staging bytes in that bridge are now tighter too: across the checked Alternate USA, Southern Pacific, and Spanish Mainline map/save pairs, payload +0x33 stays 0, but payload +0x22 and token block +0x23..+0x32 do not preserve the earlier map-to-save pairing seen at +0x14/+0x3b2. Instead they split by the finer file family, with examples Alternate USA.gmp = 0x53 / 0131115401... versus Autosave.gms = 0xae / 01439aae01..., Southern Pacific.gmp = 0xeb / 00edeeeb... versus p.gms = 0x21 / 0100892101..., and Spanish Mainline.gmp = 0x5b / 0044f05b... versus g.gms = 0x7a / 0022907a.... So the validated launch bridge now looks more like a file-family staging lane than a simple copy-forward of the earlier setup summary fields. The destination-side consumers are tighter now too: [profile+0xc4] is no longer just an unnamed staged byte, but the campaign-progress slot later consumed by the numbered %s%02d.gmc save helper 0x00517c70; [profile+0x7d] is the same compact option byte mirrored back into the Setup.win option controls 0x0ce9..0x0ced; and the campaign-side selector block is no longer only a one-byte anchor. Direct RT3.exe disassembly of the campaign-side dispatcher at 0x004b89c0 now shows the exact mirror shape: when the local campaign-page selector [window+0x78] <= 4, the helper writes one highlighted progress control 0x0c372 + [profile+0xc4] and then mirrors the full sixteen-byte band [profile+0xc6..+0xd5] into controls 0x0c382..0x0c391 through repeated 0x540120 calls. The same body also treats [profile+0xc4] as an index into the fixed sixteen-entry scenario-name table at 0x00621cf0, whose observed entries include Go West!, Germantown, Central Pacific, Texas Tea, War Effort, State of Germany, Britain, Crossing the Alps, Third Republic, Orient Express, Argentina Opens Up, Rhodes Unfinished, Japan Trembles, Greenland Growing, Dutchlantis, and California Island. On the launch-side branch the same helper writes startup selector 6, copies the resolved campaign filename into [profile+0x11], forces [profile+0xc5] = 1, and then issues shell request 0x0cc. The lower refresh tail at 0x004b8d49..0x004b8d69 also shows the observed page-band split over the same progress byte: values < 5 pair with campaign page 1, values 5..9 with page 2, values 10..12 with page 3, and values >= 13 with page 4. So [profile+0xc6..+0xd5] is no longer a generic opaque span at all, but the staged sixteen-byte per-scenario campaign selector or unlock band consumed directly by Campaign.win. The message-dispatch side is tighter now too. The local classifier at 0x004b91d8 routes the control range 0x0c352..0x0c39b through five concrete case classes: 0x0c352..0x0c361 enter the shared selector or launch branch, 0x0c362..0x0c367 force local page 1, 0x0c368..0x0c392 force local page 2, 0x0c393..0x0c396 force local page 0, and 0x0c39b alone forces local page 3. That matches the constructor and refresh shape: the sixteen scenario selector controls live at 0x0c352..0x0c361, the four page-strip controls live at 0x0c368..0x0c36b, the six-arrow auxiliary strip lives at 0x0c36c..0x0c371, the progress band lives at 0x0c372..0x0c381, the ribbon or selector band lives at 0x0c382..0x0c391, the string or voice target lane lives at 0x0c392, the four exit controls live at 0x0c397..0x0c39a, and 0x0c39b remains the one-off special action control that spawns or dismisses the campaign-side companion object. The Campaign.win blob now exposes that structural split directly too: alongside the art-backed 0x0004c3xx records it carries anonymous zero-name records with the same 0x0bb8 / 0 / 0x0bb9 prelude but selector words in the 0x0010c3xx family. Current local extraction shows exactly 0x0010c352..0x0010c361, 0x0010c362..0x0010c367, 0x0010c393..0x0010c396, and one 0x0010c39b record, which is the same non-.imb band the message dispatcher treats as the structural selector and page-write family. Their second selector word then buckets those records under the same page-strip ids as the art-backed records: 0xc368 for 0xc352..0xc356, 0xc362, 0xc393, and 0xc39b; 0xc369 for 0xc357..0xc35b, 0xc363, and 0xc394; 0xc36a for 0xc35c..0xc35e, 0xc365..0xc366, and 0xc395; and 0xc36b for 0xc367, 0xc35f..0xc361, and 0xc396. One final anonymous record at 0x0002c392 has no page bucket at all, which fits the already-grounded read of 0xc392 as the one-off string or voice target lane rather than a normal page-cell control. The anonymous body layout is only partially named, but one file-side distinction is already stable: the ordinary structural selector/page records all carry footer words 0xd3000000 and 0xd2000007 at relative +0x98/+0x9c, while the lone 0xc392 record carries 0x00000000/0x00000000 there. So 0xc392 is no longer just “outside the page buckets”; it is also the only current anonymous-record outlier in that trailing structural footer pair. The structural selector side is tighter now too: 0xc352..0xc361 partition exactly as 5 + 5 + 3 + 3 across page buckets 0xc368..0xc36b, matching the observed campaign page bands for scenario progress values < 5, 5..9, 10..12, and >= 13. That makes the anonymous selector records the file-side mirror of the same campaign page split, not a separate unrelated control family. The file-order adjacency is tighter in the same way: 0xc352..0xc361 each sit immediately after one RibbonN.imb record and before the next litCamp record, which makes them the strongest current file-side fit for the structural selector or click-target siblings of the visible campaign ribbon controls. The auxiliary anonymous bands line up the same way: 0xc362..0xc367 sit inside the local litArrows.imb clusters, 0xc393..0xc396 sit inside the litExits.imb clusters, and 0xc39b sits once between the first arrow and first exit group. So the current best read is that those anonymous records are the structural hitbox or action siblings of the visible arrow, exit, and selector art families, not an unrelated hidden control layer. The generic record cadence is tighter now too: in the current Campaign.win dump the ordinary anonymous structural records all span 0x0a7 bytes, while the named art-backed records cluster at 0x0b1, 0x0b2, and 0x0b3. The only two visible outliers are the leading 0x0080c351 record at 0x0041 with span 0x0a3, and the trailing 0x0002c392 record at 0x2fb9 with span 0x0b1. That reinforces the current read that 0xc351 and 0xc392 are one-off structural controls flanking the main selector or page family rather than ordinary repeated art-backed records. The setup-launch corpus now tightens one corrective caveat there too: when the checked Alternate USA, Southern Pacific, and Spanish Mainline .gmp/.gms files are decoded with that same campaign-side interpretation, payload byte +0x22 is always outside the known campaign progress range 0..15 (0x53, 0xeb, 0x5b, 0xae, 0x21, 0x7a), so the ordinary validated setup lane is not simply staging a normal campaign-screen state. The paired token block +0x23..+0x32 is still structurally compatible with the campaign selector band, but in the checked files it only populates a small recurring subset of the sixteen scenario lanes, chiefly Go West!, Germantown, Central Pacific, Texas Tea, and War Effort, with scenario-family-specific byte values rather than a simple 0/1 unlock bitmap. That makes the setup-side staging bridge look more like one shared destination layout being reused for a broader launch token family, not a proof that ordinary setup-launched .gmp/.gms content is already in campaign-screen form. Only 0x0e81 also sets [0x006cec7c+0x82] = 1, which is currently the strongest sandbox-side anchor beneath the later .gmx load family. That launch band is slightly tighter now too: 0x0dca is the grayscale-map picker branch above the TGA Files (*.tga) / .\Data\GrayscaleMaps helper at 0x004eb0b0, not another ordinary save-file validator. That launch band is tighter in a second way too: 0x0ddf is not a lobby branch after all, but the separate windowed-mode-gated grayscale-heightmap generation path. It reopens the TGA Files (*.tga) / .\Data\GrayscaleMaps picker through 0x0042a970, validates the chosen image through 0x005411c0, and only then writes startup selector 2. The fixed- button side is tighter too: submode 15 now aligns with the Extras family because it sits above the Readme/Weblinks shell-open quartet and the return-to-extras sibling, while submode 17 now aligns with the tutorial chooser because it is the only branch that later exposes startup selectors 1 and 7, which RT3 uses for Tutorial_2.gmp and Tutorial_1.gmp. The map-root family is tighter too: submodes 7/8/9 are the only setup branch that flips the file root into maps\\*.gm*, with mode 8 specifically the grayscale-heightmap picker and mode 9 the file-backed map-list sibling. Submode 13 is slightly tighter now too: current local evidence shows that it stays outside both the dedicated file-backed pane and the mode-3 option-heavy pane, so it is best read for now as one top-level non-file-backed setup branch rather than another saved-game list variant. The setup-side file roots are tighter now too: the shared file-list builder at 0x4333f0 formats either saved games\\*.smp or maps\\*.gm* from the shell-state fields at [0x006cec74+0x68/+0x6c], with the separate data\\tutorial root only appearing on the tutorial-side [shell+0x6c] == 2 branch. That means the Setup.win submode families are no longer one generic file pane: the ordinary setup-backed .smp family is broader than the narrower file-list pane, because modes 3/4/5/6/10/12/14 stay on the ordinary saved-game side while only 4/6/9/10/12/14 re-enter the dedicated file-list panel at 0x5027b0; the maps branch is the narrower setup or tutorial launch family above the same shared record builder.
  • Evidence: function-map map/scenario rows, analysis-context exports for 0x00445ac0, 0x00445de0, 0x00443a50, 0x00434300, and 0x00444dd0, plus objdump string and mode-table evidence for .gmp, .gmx, .gmc, .gms, .gmt, .smp, Quicksave, the 0x004dd010 mode table at 0x005f3d58, the auxiliary-owner presence check at 0x00434050, and the .gmt handoff through 0x00469d30, together with localized string evidence from ids 3018 and 3898.
  • Open Questions: bit 0x1 on both broad coordinators now grounds the Quicksave name seed and the former third fileopt.win flag has been ruled out as a file-flow question because it just opens SettingsWindow.win. The old broad extension question is mostly resolved: .gmp is the editor-map pair, .gms is the standalone scenario family, .gmc is the campaign-scenario family, .gmx is the sandbox family, and .gmt is at least bounded as an auxiliary preview-surface branch rather than another gameplay save family. The higher-value global question is no longer whether 0x00443a50 is world entry. It is where the long-lived simulation cadence takes over after this bring-up and whether that cadence still rendezvous with the shell-owned frame path or escapes into a separate gameplay loop.

Multiplayer Session and Transport Flow

  • Roots: multiplayer_window_init_globals at 0x004efe80, multiplayer_window_service_loop at 0x004f03f0, the Multiplayer.win session-event callback table built by multiplayer_register_session_event_callbacks at 0x0046a900, the active session-event transport object at 0x006cd970, the Multiplayer preview dataset object at 0x006cd8d8, and the lower pending-template and text-stream helpers around 0x00597880..0x0059caf0.
  • Trigger/Cadence: shell-owned Multiplayer.win frame service plus event-driven session callbacks and repeated transport pump steps.
  • Key Dispatchers: session-event wrappers for actions 1, 2, 4, 7, 8; multiplayer_register_session_event_callbacks; multiplayer_dispatch_requested_action; multiplayer_reset_preview_dataset_and_request_action; multiplayer_preview_dataset_service_frame; multiplayer_load_selected_map_preview_surface; multiplayer_flush_session_event_transport; multiplayer_transport_service_frame; multiplayer_transport_service_worker_once; multiplayer_transport_service_route_callback_tables; multiplayer_transport_service_status_and_live_routes; multiplayer_transport_text_stream_service_io; multiplayer_transport_dispatch_pending_template_node; multiplayer_transport_service_pending_template_dispatch_store.
  • State Anchors: live session globals at 0x006d40d0, active session-event transport object at 0x006cd970, status latch at 0x006cd974, session-event mode latch at 0x006cd978, retry counter at 0x006cd984, preview dataset object at 0x006cd8d8, preview-valid flag at 0x006ce9bc, staged preview strings at 0x006ce670 and [0x006cd8d8+0x8f48], Multiplayer.win backing block at 0x006d1270, selector-view store root at [transport+0xab4], selector-view generation counters at [transport+0xab8]..[transport+0xac0], selector-view backing arrays around [transport+0xad0]..[transport+0xae4], selector-view entry probe-request id at [entry+0x50], live-state gate at [entry+0x58], third-slot flag word at [entry+0x64], probe-schedule tick at [entry+0x68], last-success tick at [entry+0x6c], pending-probe latch at [entry+0x74], success generation at [entry+0x78], consecutive-failure counter at [entry+0x7c], rolling average at [entry+0x80], recent sample window at [entry+0x84..], bounded sample-count at [entry+0x94], total-success count at [entry+0x98], pending-template list at [transport+0x550], dispatch store at [worker+0x54c], and text-stream buffers rooted under [worker+0x1c].
  • Subsystem Handoffs: the Multiplayer.win initializer seeds the backing block at 0x006d1270, later reset paths construct the separate preview dataset at 0x006cd8d8, and the shell-owned active-mode frame services that dataset every frame through multiplayer_preview_dataset_service_frame. That preview side publishes roster and status controls through the Multiplayer window control paths, loads .gmt preview surfaces through multiplayer_load_selected_map_preview_surface, and is even reused by the map/save coordinators mode-11 .gmt path when the dataset already exists. In parallel, multiplayer_register_session_event_callbacks allocates and registers the separate session-event transport object at 0x006cd970. The shell-side bridge into that deeper transport cadence is now tighter: multiplayer_window_service_loop and neighboring reset or initializer branches call multiplayer_flush_session_event_transport, which forces one status flush and then drops into multiplayer_transport_flush_and_maybe_shutdown. That wrapper in turn runs multiplayer_transport_service_frame, the recurring pump that services one worker step through multiplayer_transport_service_worker_once, sweeps the transport-owned callback tables and field caches through multiplayer_transport_service_route_callback_tables, services both the auxiliary status route and the current live route through multiplayer_transport_service_status_and_live_routes, and then descends one layer farther into the shared GameSpy route helper multiplayer_gamespy_route_service_frame at 0x58d040. The transport also owns a separate selector-view sidecar beneath that route cadence. multiplayer_transport_ensure_selector_view_store allocates the keyed selector-view store at [transport+0xab4], multiplayer_transport_find_selector_view_entry_by_name resolves entries from that store, multiplayer_transport_upsert_selector_name_entry marks per-slot activity and flags inside each entry, and multiplayer_transport_mark_selector_slot_views_dirty plus multiplayer_transport_reset_selector_view_entry_runtime_state manage the dirty or refresh fields at +0xa0, +0xa4, and +0xa8. That selector-view maintenance path is now split more cleanly too. The recurring owner is multiplayer_transport_service_selector_view_refresh_cycle, which first runs the fast deferred-probe lane: multiplayer_transport_collect_refreshable_selector_view_entries walks the store through multiplayer_transport_filter_insert_refreshable_selector_view_entry, which now shows that [entry+0x64] is not a generic flag bucket but the third selector-slot flag word, parallel to [entry+0x5c] and [entry+0x60]. In that collector, the g and a mode-letter bits produced by multiplayer_transport_parse_selector_mode_letters become mask 0x0c in the slot-local flag words, and any third-slot entry carrying those bits at [entry+0x64] is excluded from the refreshable set. Eligible entries then pass slot-aware retry timing on [entry+0x68], [entry+0x6c], [entry+0x78], and [entry+0x7c], after which the service loop schedules refresh probes through multiplayer_transport_schedule_selector_view_entry_refresh_probe. That fast lane is narrower now too: the entry-side match key [entry+0x50] is no longer just an opaque request field. The profile-key callback lanes feed multiplayer_transport_parse_selector_view_probe_marker, which decodes one local X%sX|%d marker into a probe request id plus displayed version/build integer, and multiplayer_transport_arm_selector_view_probe_tracking stores those into [entry+0x50] and [entry+0x54] before arming the live probe gate at [entry+0x58]. The current-selector callback root at 0x59f8b0 is now bounded as well: it resolves and upserts the active selector name, optionally reuses a cached username marker to arm probe tracking immediately, then submits the same profile-key bundle with selector context and forwards that selector through callback slot 17, with the status-route side able to force route-mode transitions 2 -> 3 -> 4 afterward. One layer lower, multiplayer_transport_handle_profile_key_query_result at 0x596970 now bounds the per-key result path itself. It treats username as the probe-marker field, b_flags as the selector mode-letter field, and (END) as a real sentinel that publishes a zeroed slot-22 payload instead of a marker pair. The same helper also hashes the selector-name, key-name, and resolved value text back into the caller table, so the profile-key bundle now looks like a real bounded handoff rather than an anonymous callback cloud. The deferred callback shim multiplayer_transport_dispatch_selector_view_refresh_probe_result then walks the keyed store through multiplayer_transport_finish_selector_view_refresh_probe_if_matching, which only completes entries whose pending latch [entry+0x74] is still armed and whose parsed marker request id [entry+0x50] matches the finished request. A failed result -1 clears the pending latch and increments the consecutive-failure counter at [entry+0x7c]. A nonfailure result clears the pending latch, increments the success generation at [entry+0x78] and total-success count [entry+0x98], clears [entry+0x7c], stamps the last-success tick at [entry+0x6c], appends the returned sample into the short rolling history at [entry+0x84..], grows the bounded sample-count [entry+0x94] up to four, computes the current average into [entry+0x80], and then publishes that averaged ms sample through multiplayer_transport_enqueue_callback_slot24_record. So the publication boundary is explicit and the request-id ownership is explicit: [entry+0x80] now reads as the averaged millisecond probe sample and [entry+0x54] as the displayed version/build companion integer. The adjacent route-callback side is tighter too, but it is now kept separate: the staged route-callback path at 0x5958e0 and the later compatibility gate at multiplayer_transport_route_binding_matches_route_callback_descriptor_tuple 0x595d00 operate on a compact GameSpy-style server or route descriptor family with a primary endpoint tuple at [descriptor+0x00]/[+0x04], an optional secondary endpoint tuple at [descriptor+0x08]/[+0x0c], string-key lookups such as hostname and gamever, and numeric-key lookups such as numplayers, numservers, numwaiting, and gsi_am_rating. The route-binding side uses that descriptor family's primary dword and host-order port plus the optional secondary tuple against route-binding offsets +0x54/+0x58 and route word +0x30. Current evidence still does not prove that descriptor tuple is the same field family as the selector-view marker companion integer at [entry+0x54]. The higher compact decode owners are tighter now too: 0x5907d0 is the allocate-and-append lane for one self-consistent compact payload, while 0x590d00 is the keyed upsert-by-primary-endpoint lane that reuses an existing descriptor when possible and then notifies the owner callback. The route-callback-table runtime above that decode side is tighter now too: multiplayer_transport_route_callback_table_construct 0x5905e0 seeds one transport-owned table block, multiplayer_transport_route_callback_table_release_decoded_schema_dictionary 0x5906f0 tears down the decoded schema dictionary rooted at [this+0x08], multiplayer_route_callback_runtime_acquire_shared_string_copy 0x590540 and multiplayer_route_callback_runtime_release_shared_string_copy 0x5905a0 now bound the shared string pool used by that decoded schema, and the higher bring-up owner 0x596090 now clearly splits between [transport+0xba4] with owner callback 0x595a40, the local field-cache family [transport+0x1724] seeded through 0x5a08f0/0x595b60, and [transport+0x1164] with owner callback 0x595bc0, while multiplayer_transport_route_callback_table_service_receive_decode_state_machine 0x5908c0 is the current live receive/decode state machine serviced by 0x591290 in table states 2/3. The callback-owner mode split above that runtime is now explicit too: append-notify 0x590370 publishes mode 0, compact upsert 0x590d00 publishes mode 1, remove-notify 0x590430 publishes mode 2, and the live receive/decode path 0x5908c0 publishes modes 6, 5, and 3. The route-handle lifecycle above that decode path is tighter now too: 0x590740 cleanly resets one table's live route plus decode-side runtime without destroying the outer object; 0x5907a0 is the broader destroy path that also releases the active descriptor collection; 0x590ed0 opens the live route handle into [this+0x4a0], stages the initial outbound request, and seeds state 3 plus the staged receive buffer; 0x5911e0 is the state-2/3 socket-service wrapper that reads new bytes, grows the staged buffer, and re-enters 0x5908c0; 0x5912c0 is the one-shot send-with-reopen-retry helper; and 0x590ea0 is the shared disconnect publication and reset tail. The recurring service helper 0x591290 is tighter too: it now first clears the staged intrusive descriptor list through 0x590490 before entering the state-driven seed-or- receive branch. The upstream owners are tighter too: 0x5962e0 is now the field-subscription route-table opener above [transport+0xba4], while 0x596530 is the gsi_am_rating reopen path above [transport+0x18bc]. On that latter branch, 0x590dc0 is now bounded as the state-0 raw-endpoint seed pass over the live route handle, repeatedly pulling endpoint tuples through 0x58bc7e record type 0x1f3 before stamping descriptor flag byte 0x15 with 0x11. That makes the remaining source-flag meaning narrower too: current evidence now supports reading byte-0x15 bit 0x1 as a primary-endpoint-seed or endpoint-only marker. In the gsi_am_rating dispatcher, clear-bit descriptors can take the richer direct transition lane, while set-bit descriptors are staged through the queued enrichment path and still suppress that direct transition even after the ready bit arrives. The adjacent capacity-descriptor side is tighter too: 0x595bc0 now clearly publishes a descriptor block from live descriptor properties hostname, numwaiting, maxwaiting, numservers, and numplayers plus three carried sidecar scalars. That sidecar at [transport+0x1778] is tighter now too: current evidence says it behaves as one cached pointer into the transient work-record family at [transport+0x1780], because every meaningful branch in 0x595bc0 reads the same +0x0c/+0x10/+0x18 metadata triplet and replay modes later consume the pointer through 0x5933a0. The negative result is stronger too: local text-side xrefs still show no direct store to [transport+0x1778], and a wider local sweep also failed to show any obvious lea-based replay-band writer. The transient-request lifecycle tightens that further: 0x593330/0x593370/0x593380/0x5934e0/0x5933a0 now fully bound [transport+0x1780], 0x1784, and 0x1788 without ever touching [transport+0x1778], and the neighboring active-opcode reset helper 0x5929a0 is likewise scoped only to [transport+0x17fc]. A broader constructor and teardown pass tightened that further too: 0x596090, 0x5961b0, and 0x5962e0 all touch the neighboring replay-band fields without ever seeding [transport+0x1778]. A full-binary literal-offset sweep tightens it further still: the only direct 0x1778 hit in RT3.exe is the read in 0x595bc0. One nearby ambiguity is now closed too: the mode-5 mirror path in 0x595a40 and 0x595e10 does not target [transport+0x1778]; it writes [transport+0x54] and mirrors the same staged route companion dword only into queue-side slot [transport+0x1724+0x24] through 0x005a0940. So the sidecar writer remains upstream of this leaf publisher. Mode 0 is now also tied more cleanly to the generic descriptor append-notify lane at 0x590370, while mode 2 stays outside this helper as the separate remove-notify-and-stage path at 0x590430. The opcode-2 payload boundary is tighter too: 0x592ae0 now grounds that payload as a seven-dword block with an owned string slot at +0x08, so live mode supplies a populated payload while modes 3 and 5 deliberately enqueue an all-zero payload and reuse only the wrapper-side sidecar metadata. Those two modes are tighter now too: they are the live receive-state owner callbacks emitted by 0x5911e0 -> 0x5908c0, not loose generic replay guesses. So those paths are better read as delayed metadata replays over one cached work record, not over a separate anonymous cache blob. The neighboring capacity-owner split is tighter now too: 0x595bc0 only stages descriptor records for modes 0, 3, and 5; the upstream route-callback-table owner still delivers modes 1, 2, and 6, but those are explicit no-ops in this capacity leaf. So the owner wiring itself is no longer the open edge; only the upstream sidecar producer remains unresolved. The neighboring work queue is tighter too: 0x593330/0x593370/0x593380 now bound [transport+0x1780] as the construct/clear/destroy owner family, while 0x5933a0, 0x5934e0, and 0x593570 ground the remove, allocate, and completion side over that same collection. The small sibling 0x593400 is tighter too: it is a pure work-record uniqueness predicate over field +0x0c. Its caller is tighter now too: 0x58d720 is an immediate-drain quiescence gate over one transport context id, using 0x593400 for the queued work family at [transport+0x1780] and 0x592970 for the active opcode-record collection at [transport+0x17fc]. The strongest current read is that 0x5934c0 seeds that shared drain context id first, then the transport copies it into queued work field +0x0c and active opcode-record field +0x14 before the immediate-drain roots wait on one shared disappearance test rather than on a vague settle loop. The currently grounded roots are 0x58df20, the neighboring formatted selector-text publish path at 0x58dfb0, and callback-table registration at 0x58e200. The active-opcode side is tighter too: 0x5927b0 now bounds the per-record service-and-retire path, 0x592800 the wider context-or-idle sweep, 0x5929a0 the remove-by-opcode-type sweep, and 0x5929f0 the narrower opcode-3 field-snapshot removal keyed by the subscribed callback-pair payload. That also corrects 0x595b80, whose final cleanup is an active field-snapshot purge rather than a queued-work drain. The adjacent route-callback descriptor-table lifecycle is tighter too: 0x590410 now grounds [table+0x5bc] as the staged intrusive descriptor-list head, 0x590430 is the generic remove-notify-and-stage lane, 0x590490 releases the staged list, and 0x5904d0 releases the active descriptor collection before tearing that staged list down. That also makes the earlier 0x5962e0 “release active descriptors” step explicit. The callback-table attach side now constrains the same work-record metadata family a little further too: 0x593650 deliberately duplicates its first caller metadata dword into both fields +0x0c and +0x10, while carrying the second caller metadata dword in +0x18. The lower opcode wrappers are tighter now too: 0x592a40 turned out to be the explicit opcode-1 trigger wrapper whose constructor is a no-op and whose active-side service is 0x5913c0, while 0x592c40 is the real 0x08-byte explicit opcode-5 binding leaf. The earlier opcode-4 read was just the table-indexing mistake in 0x5928a0: selector 4 lands on the row at 0x5e2044, not the row at 0x5e2034. The producer side is tighter too: bound-route requests, selector-text route requests, and the type-9 text fastpath also stage that same triplet through 0x5934e0, and the fastpath shim 0x593d00 now gives the cleanest proof of the callback split by only re-emitting the follow-on lane when +0x10 is nonnull and then forwarding (+0x10, +0x18, +0x0c) into 0x593170 as callback function, callback companion, and trailing drain context. So the replay-side triplet is clearly a broader transport callback-wrapper family, not one fixed route-only tuple. The nearby field-subscription side is tighter too: 0x592b50 now clearly uses [transport+0x1774] as a cached progress percentage under [transport+0xba4], and 0x5962e0 seeds that percentage to 1 just before the first immediate mode-3 snapshot. The nearby route-callback-table lifecycle is tighter now too: 0x596090 seeds [transport+0xba0] as the callback-plumbing enable latch, clears staged payload slot [transport+0xb50], and constructs the three owner branches rooted at [transport+0xba4], [transport+0x1164], and [transport+0x18bc]; 0x596210 is the recurring service sweep over those same three tables plus the local field cache and queued-descriptor family; 0x596060 is the explicit gsi_am_rating reset; and 0x596530 is the reopen-from-stored-label sibling above that same am-rating table. The matching local cleanup is tighter too: 0x5962c0 is the explicit staged route-callback payload clear on [transport+0xb50], while 0x595ce0 now clearly resets only the capacity-descriptor route callback table at [transport+0x1164], not the field-subscription table at [transport+0xba4]. The remaining gap on the capacity side is therefore narrower: the carried sidecar fields themselves now read more cleanly as the cached callback-wrapper triplet reused elsewhere (drain context id +0x0c, callback fn +0x10, callback companion +0x18), and the negative result is stronger too: nearby replay-band fields [transport+0x176c], [transport+0x1770], [transport+0x1774], [transport+0x177c], [transport+0x1780], and [transport+0x1784] all have direct local owners while [transport+0x1778] still appears only as the single read in 0x595bc0; even the broader callback-owner lifecycle now skips it while seeding, servicing, resetting, reopening, or tearing down those neighboring tables and caches. The constructor now closes that local search further: 0x58dc50 bulk-zeroes the full transport body and still never writes a nonzero value into [transport+0x1778] before later explicit neighbor initialization. The callback-binding owner stack now tightens that boundary too: 0x5934e0 stages the shared work-record metadata triplet, 0x593650 binds it into the callback-table worker path, and 0x593570 later consumes and republishes it, while [transport+0x1778] still appears only as the borrowed sidecar read in 0x595bc0. So this edge is now locally closed, and the remaining producer looks like an upstream callback or worker handoff rather than one missing ordinary field store in the local cluster. The adjacent staged-route callback side is tighter too: 0x595860 is now bounded as the submit-result handler beneath 0x5958e0, and the old [transport+0xac0] ambiguity there is now gone. That branch is using the already-grounded third selector-generation counter at [0xac0] together with target [0xb48] to decide whether staged route-callback traffic can push the multiplayer route-mode ladder from 2 into 3 and later 4. The selector-view counter beneath that gate is tighter now too: 0x594e30 counts slot-2 entries whose flag dword carries bit 0x20, optionally filtered by the current transport name buffer. The selector-view mutation family under that same lane is tighter too: 0x594a30 is now the direct keyed-store remover, 0x594fb0 clears one selector-slot ownership pointer plus its slot-local flag dword and drops the whole entry when no slots remain, 0x595010 rekeys one selector-view entry under a new name while preserving the 0x40.. runtime band, and callback root 0x59f9c0 now reads as the sibling lane that clears one named selector-view slot, publishes callback slot 18, and may still re-enter the route-mode setter from the same slot-2 status and generation gates. The neighboring callback roots are tighter now too: 0x5950a0 clears one selector slot from every selector-view entry in the keyed store, 0x59fab0 is the rename or relabel sibling above 0x595010, 0x59faf0 updates one selector slot's fixed sample-text buffer and refreshes the active selector object when present, and 0x59fb60 replaces one selector slot's name set, requests the default profile-key bundle for that slot, and publishes callback slot 20. Slot 16 is tighter now too: current grounded caller 0x59f440 forwards the staged route-callback payload handle from [transport+0xb50] through 0x592ea0 just before route mode 5. The last adjacent callback root in that block is tighter now too: 0x59fbd0 is the built-in per-slot profile-key query sibling. It resolves the caller selector name into one slot index, forwards the caller trio into 0x596b90, and then publishes callback slot 28; that lower helper indexes one slot-specific built-in string pair from [transport+0x189c] and [transport+0x18ac], reuses the generic per-key handler 0x596970, and only republishes slot 28 when that lower query path succeeds. The compact-header side is tighter now too: 0x58fe20 and 0x58ff20 now show that compact payloads always carry the primary IPv4 dword and that header bit 0x10 only gates whether the primary port word is inline or inherited from the owner default port. 0x58fe90 now validates the 0x40 inline keyed-property vector against the owner schema, and 0x58fe50 validates the signed-0x80 trailing string-pair tail before decode. 0x58ff60 then grounds bit 0x02 as the inline secondary IPv4 dword branch, bit 0x20 as the paired secondary-port word branch with owner-port fallback, bit 0x08 as one still-unresolved auxiliary dword stored at [descriptor+0x10], bit 0x40 as one inline keyed-property vector decoded through the property-store writers, and signed bit 0x80 as one trailing string-pair tail. The descriptor-state side is tighter now too: the shared queue helper at 0x005a09a0 stamps pending state 0x4 for the local field-cache family [transport+0x1724] and pending state 0x8 for the gsi_am_rating queued-descriptor family [transport+0x1e7c], while later service through 0x005a0c80 promotes those pending tags into ready bits 0x1 and 0x2 in descriptor byte [entry+0x14]. That makes the current transport-side tests cleaner: 0x58d1c0 is the field-cache ready gate, 0x58d1d0 is the gsi_am_rating queued-descriptor ready gate, and 0x58d230 is the remaining flag-byte split between direct primary-endpoint handling at [transport+0x18bc] and the queued path at [transport+0x1e7c]. That byte-0x14 story is no longer queue-only either: 0x58ff60 can also OR in bit 0x1 after the inline keyed-property vector and bit 0x2 after the signed string-pair tail. The flag-byte split is no longer purely behavioral either: current evidence now says byte [descriptor+0x15] bit 0x1 is a source-side descriptor header bit, explicitly seeded during the primary-endpoint table refresh around 0x590dc0 and preserved by the compact descriptor decode path at 0x58ff60, rather than a queue-generated runtime state. The gsi_am_rating dispatcher side is tighter too: that same bit no longer just looks like a direct-versus-queued routing split, because 0x595e10 also uses it to suppress the direct 0x595dc0 transition even after queued ready bit 0x2 is present. The descriptor body is tighter too: [descriptor+0x20] is now the intrusive next-link used by the transport-owned primary-endpoint list headed at [table+0x5bc], and [descriptor+0x1c] is now the special numeric scalar behind the current queryid/ping fallback pair. The compact-only auxiliary dword at [descriptor+0x10] is tighter in a negative way too: local xref scans now only show it being preserved by later generic helpers like generic_record_0x1c_deep_copy_with_owned_string_at_0x08 0x591410 and the adjacent callback-marshaling wrappers 0x591480 and 0x591510, not read through any dedicated semantic accessor yet. The route-event dispatcher side is tighter too: the mode-5 tails in both callback families do not copy a descriptor-local field but instead mirror the transport-staged companion dword at [this+0x490] into [this+0x54] and queue-side slot [this+0x1724+0x24]. The gsi_am_rating maintenance lane is tighter now too: after pruning failed descriptors it sorts the surviving primary-endpoint table through 0x590310 in mode 1 with key gsi_am_rating, then selects the new head through 0x590480 before re-entering the route-transition path. The same service loop also owns a slower sidecar lane keyed off [entry+0xa4]: multiplayer_transport_select_stale_selector_view_progress_entry walks the store through multiplayer_transport_pick_stale_selector_view_progress_entry, picks one stale entry whose progress latch [entry+0x9c] is clear and whose last progress tick [entry+0x70] is old enough, and then hands it to multiplayer_transport_stage_selector_view_progress_snapshot. That helper now looks more bounded too: it rebuilds the core X%sX marker text from [entry+0x50] through multiplayer_transport_format_selector_view_probe_marker_core, formats one PNG %s %d line around that marker and the entry-local averaged millisecond sample at [entry+0x80], appends bounded selector-slot PNG fragments for live overlapping slots, marks progress-snapshot state in flight at [entry+0x9c], and stamps both [entry+0x70] and the transport-wide throttle tick [transport+0xaec]. So the selector-view sidecar no longer looks like one undifferentiated refresh bucket: it has a faster deferred-probe lane plus a slower progress-snapshot lane, both still under the shell-owned multiplayer transport cadence. The two descriptor lanes installed by multiplayer_transport_attach_callback_table_descriptor are now tighter too. The first lane rooted at 0x59f5c0 can arm deferred-close state on the owner transport and then forward through callback slot 23. The second lane is no longer just a loose selector-view bucket: multiplayer_transport_callback_dispatch_selector_name_payload_lane at 0x59f650 classifies selector payloads through multiplayer_transport_is_selector_control_line, routes @@@NFO control lines into multiplayer_transport_sync_selector_view_nfo_r_flag, and otherwise publishes either callback slot 13 or the split token-plus-tail callback slot 14 through multiplayer_transport_split_selector_payload_token_and_tail. That local @@@NFO helper is now bounded more tightly too: it only accepts lines ending in the literal X\ tail, searches for the field marker \$flags$\, and then sets or clears bit 0x2 in the third selector-slot flag word at [entry+0x64] depending on whether that field contains the letter r before the next backslash. The sibling multiplayer_transport_callback_dispatch_current_selector_payload_lane at 0x59f720 first resolves the active selector through 0x5951a0, then handles the current-selector variants of the same control vocabulary: @@@NFO continues into the same local r-flag sync helper, @@@GML plus mode-3/4 payloads feed the shared control-token helper multiplayer_transport_handle_gml_or_png_selector_control, and the remaining non-control payloads publish callback slot 9. That shared helper now narrows the GML and PNG split materially: when the token is GML and the tail is Disconnected, it requires the active selector-view entry to pass multiplayer_transport_selector_view_entry_has_gml_disconnect_gate, which currently means the entry participates in the third selector slot and has bit 0x20 set in [entry+0x64], before it forces one status-pump pass, emits callback slot 16, and re-enters route mode 5. Its sibling PNG branch resolves a named selector-view entry from the tail text and, when that entry overlaps the active selector-slot ownership, refreshes selector-view runtime state through 0x5948f0 and republishes callback slot 25. Alongside those dispatchers, one grounded branch at 0x59f560 still updates selector-view runtime state through 0x5948f0 and forwards the same selector-name pair through callback slot 25, while 0x59f850 resets selector text state through 0x5954b0, forwards through callback slot 19, and when selector 2 is active in a nonterminal route mode re-enters multiplayer_transport_set_route_mode with mode 1. The low-level route helper still looks like a two-part cycle: multiplayer_gamespy_route_service_retry_and_keepalive_timers handles challenge or retry pressure and periodic outbound control traffic around the master.gamespy.com, PING, natneg, localport, localip%d, and statechanged strings, while multiplayer_gamespy_route_drain_inbound_packets drains inbound datagrams and dispatches semicolon lines, backslash-delimited key bundles, and 0xfe 0xfd GameSpy control packets. The transport-owned callback story is now narrower too. The shared route constructor multiplayer_gamespy_route_construct_and_seed_callback_vector seeds [route+0x88] through [route+0x9c] from the caller-supplied transport callback table, records the owner transport at [route+0x104], and explicitly zeroes [route+0xa0], [route+0xa4], and [route+0xd4] before any later patch-up. For the transport-owned status route, multiplayer_transport_try_connect_status_route then patches [route+0xa0] through multiplayer_gamespy_route_set_extended_payload_callback to point at multiplayer_transport_forward_validated_extended_route_payload 0x00597330, which simply forwards the validated payload wrapper into the owner callback at [transport+0x17f4] with context [transport+0x17f8]. The grounded live-route connect path at multiplayer_transport_try_connect_live_route does not currently perform any matching post-construction patch for [route+0xa0], [route+0xa4], or [route+0xd4], and the higher route-mode state machine now looks consistent with that: multiplayer_transport_set_route_mode latches the requested small mode at [this+0x18b8], then uses mode 0 for the direct-versus queued gsi_am_rating split, mode 1 for the ready-bit plus queued fallback, mode 2 for pending-descriptor cleanup, mode 3 for the empty-table fallback, mode 4 for deferred route-status recovery, and mode 5 for copying the staged route companion dword into [this+0x54] and queue-side slot [this+0x1724+0x24]. The current grounded mode transitions still switch by releasing route objects through multiplayer_gamespy_route_release_and_free and rebuilding them through multiplayer_transport_try_connect_live_route, not by mutating callback slots in place. The parser behavior is now tighter as well: semicolon lines only dispatch when [route+0xd4] is non-null, and the subtype-6 raw fallback only dispatches when [route+0xa4] is non-null. For the currently grounded transport-owned status and live routes, those two branches therefore remain optional and can cleanly no-op instead of implying a hidden mandatory callback path. Inside the packet parser, subtype 4 is no longer an unknown callback hop: after cookie validation it dispatches through [route+0x9c], which the transport-owned status and live routes seed to multiplayer_transport_handle_validated_route_cookie_event 0x005972c0. That helper either marks route progress and re-enters multiplayer_transport_set_route_mode, or forwards the event id plus payload into the owner callback at [transport+0x17f0] with context [transport+0x17f8]. The surrounding status-route callback vector is tighter now too: 0x005970e0 publishes either the active selector text or the averaged probe sample at [entry+0x80] and otherwise falls back to owner callback [transport+0x17e0]; 0x00597180 is a straight owner-forwarding lane through [transport+0x17e4]; 0x005971b0 seeds the local status-control id list and can then notify owner callback [transport+0x17e8]; and 0x00597270 returns the third selector-slot generation counter [transport+0xac0] on its bounded local branch before falling back to owner callback [transport+0x17ec]. Subtype 6 still validates the same cookie, dedupes one 32-bit cookie or packet id, and then dispatches the trailing payload through the natneg-or-raw callback layer rooted at [route+0xa0] and [route+0xa4]. This separates the shell-frame preview refresh at 0x006cd8d8 from the actual transport cadence at 0x006cd970, and also separates that transport cadence from the lower GameSpy route-service and packet-parser layer beneath it.
  • Evidence: function-map.csv, pending-template-store-management.md, pending-template-store-functions.csv, plus objdump caller traces showing multiplayer_window_service_loop reaching multiplayer_flush_session_event_transport and the transport pump chain multiplayer_flush_session_event_transport -> multiplayer_transport_flush_and_maybe_shutdown -> multiplayer_transport_service_frame -> multiplayer_transport_service_worker_once -> multiplayer_transport_drain_request_text_queue.
  • Open Questions: unresolved request-id semantics for 1, 2, 4, and 7; whether any non-mode-path helper outside the currently grounded release-and-rebuild flow ever patches [route+0xa4] and [route+0xd4] for the transport-owned status/live routes, or whether those packet families are simply unused in this stack; and how far the Multiplayer preview-dataset machinery is reused outside Multiplayer.win beyond the currently grounded .gmt save-mode hook.

Input, Save/Load, and Simulation

  • Roots: the shell controller window-message ingress shell_controller_window_message_dispatch at 0x0054e3a0, the shell input-state object initialized at 0x006d4018 through shell_input_state_init 0x0054e710, the saved-world restore path world_load_saved_runtime_state_bundle at 0x00446d40, the live-world save path world_runtime_serialize_smp_bundle at 0x00446240, world_entry_transition_and_runtime_bringup at 0x00443a50, the frame-owned cadence simulation_frame_accumulate_and_step_world at 0x00439140, the recurring GameMessage.win service branch through game_message_window_service_if_present 0x004e0720, the world-facing GameUppermost.win overlay branch ensured by shell_ensure_game_uppermost_window 0x004e0e40 and serviced through game_uppermost_window_service_world_hotspot_band 0x004e0780, and the lower step family rooted at simulation_advance_to_target_calendar_point 0x0040ab50 with periodic branches through simulation_service_periodic_boundary_work 0x0040a590.

  • Trigger/Cadence: shell-side input is event-driven by controller-window WM_* traffic while save or load work is triggered either directly from shell commands or through the fileopt.win branch flags into the .smp runtime-state family; post-bring-up world service becomes recurring once a world root exists at 0x0062c120, but the current grounded top-level cadence still remains the shell-owned shell_service_pump_iteration path, which calls simulation_frame_accumulate_and_step_world directly and lets it accumulate elapsed wall-clock time into one or more simulation-step quanta. A second ingress is now bounded too: simulation_run_chunked_fast_forward_burst at 0x00437b20 repeatedly calls the same lower stepper simulation_advance_to_target_calendar_point, but current grounded callers put that helper inside the larger post-load generation pipeline world_run_post_load_generation_pipeline at 0x004384d0 under the Seeding Economy... phase rather than under the ordinary player-facing speed buttons. That setup pipeline is now clearer at the progress-banner level too: on the fuller setup path it first runs one preliminary named-candidate availability prepass through 0x00437743 before any visible progress banner is posted. After that, localized id 318 Computing Transportation and Pricing... stays visible while the pipeline runs world_compute_transport_and_pricing_grid 0x0044fb70, the early collection-owned staging pass world_rebuild_secondary_raster_derived_surface_and_companion_planes_in_rect 0x0044e940, 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. The transport/pricing side is tighter now too: 0x0044fb70 first routes one null-build path through the preview ensure wrapper 0x0044faf0, whose deeper worker 0x0044f840 allocates a default target through 0x00534930, seeds five palette entries through 0x0051de10, maps each target pixel back into the live secondary raster through 0x00533970/0x00533980, uses the low-3-bit class split plus a local +/-4 neighborhood and 0x0051db80 to choose the preview color, and only then re-enters 0x0044e940 on the full rectangle. The later 322 side is tighter now too: the top owner 0x0044d410 rejects while generation counter [world+0x2205] is live or when 0x00449e90 cannot supply a surviving work rect, then forwards that rect into 0x005374d0, 0x00533e70, and 0x00537010, notifies the shell owner at 0x0062be68, and refreshes neighboring region or manager companions through 0x00421f50, 0x00461770, and 0x00415340. The local companion-float strip under that same owner is tighter now too: 0x0044d4e0 and 0x0044d6e0 are sibling five-pass cross-neighbor relaxers over [world+0x1605]; both clamp the caller rectangle, average the four cardinal neighbors, subtract the current sample, scale the delta by one fixed coefficient and caller gain, and then feed the surviving rectangle back into 0x0044d410. The first helper only checks raster bit 0x01 in [world+0x2135], while the second adds the tighter acceptance gate 0x004499c0 and can skip the final 0x0044d410 tail when its caller disables that refresh. Their center-biased sibling 0x0044d880 is now bounded too: it seeds one baseline from the current center sample when its caller gain is positive, expands one square neighborhood by radius, and raises surrounding cells toward that baseline through the same 0x0051dc00 falloff model before tailing into 0x0044d410. The local peak-oriented sibling 0x0044da70 then raises one clamped square neighborhood by quantized local maxima and on its optional branch also consults 0x00534f00 before keeping the larger peak. So the 0x0044d4e0/0x0044d6e0/0x0044d880/0x0044da70 band now reads as the local companion-float refinement layer immediately beneath the shared Calculating Heights... owner rather than a set of unrelated scalar writes. The default-region side is tighter too: one earlier class-0-only helper 0x0041fb00 now sits directly under that same family too: it skips nonzero [region+0x23e] records, rounds the region center through 0x00455800/0x00455810/0x005a10d0, stamps one orientation-dependent local secondary-overlay pattern through 0x00534e10 plus 0x004497a0, and then runs one bounded scored refinement pass through 0x0051db80, 0x00534040, 0x005340a0, 0x00534100, and 0x00533fe0. The finalizer 0x00421730 then clears the per-cell region word at [world+0x212d] + cell*4 + 1 across the full live world raster, seeds each live region's cached bounds fields, and repopulates that same raster by writing the nearest class-0 region id [region+0x23a] into empty or weaker cell slots from one bounded center-and-radius sweep. The region-profile side is tighter too: 0x0041f940 counts only the current subcollection entries whose backing candidates pass 0x0041f998, and that smaller predicate now has one real content split instead of staying anonymous. Candidates whose subtype byte is not 2 pass immediately, while subtype-2 candidates only pass when either availability word [candidate+0xba] or runtime recipe latch [candidate+0x7ac] is nonzero; 0x00412af0/0x00412b70 now ground the lookup step beneath both counters as a casefolded profile-label-to-candidate resolver over the global candidate pool 0x0062b268; and the stricter year-filtered counter 0x0041f9b0 then stacks the category and [profile+0x26] <= year gates on top of that same availability test. That border pass is now tighter too: the outer owner refreshes the companion region set 0x006cfc9c through the reset-and-assign wrapper 0x00487650 above the heavier record initializer 0x00487540, then re-enters 0x004881b0 to refresh the raw per-region cell-count band from the live world raster, and the inner emitter 0x00487de0 clears prior chunked segment queues through 0x00533cf0, scans the live region raster, and appends fresh border-segment records through 0x00536ea0. The lower presentation helper strip under the same owner is now explicit too: 0x00533970/0x00533980 query the cached world-grid X/Y maxima, 0x00533ae0/0x00533af0/0x00533b00 expose the secondary-raster and companion byte-raster roots, and 0x00533b20/0x00533b30/0x00533b70/0x00533b90 expose the normalized coordinate, strip-offset, and sample-triplet tables used by shell-side overlay staging. If shell-state gate [0x006cec74+0x174] is set it then posts id 320 Setting Up Buildings... for world_region_collection_run_building_population_pass 0x00421c20; if [0x006cec74+0x178] > 0 it then posts id 321 Seeding Economy... for simulation_run_chunked_fast_forward_burst 0x00437b20; only after those setup-side gates does the code post id 319 Setting up Players and Companies.... That 319 lane is no longer just a shell-state placeholder: its earlier hidden prepass is tighter now too: 0x00437743 is the scenario-side named candidate-availability seeding pass over the live candidate pool 0x0062b268, feeding the override collection at [state+0x66b2] through 0x00434f20 before any visible banner is posted. That grounded write path is narrower than the static file evidence, though: the startup reset helper world_runtime_reset_startup_dispatch_state_bands 0x004336d0 explicitly clears [state+0x66b2] before the dispatch path begins, and the current exported write-side callers we can name after that reset are still just the live-pool preseed 0x00437743, the sibling startup lane 0x00436ad7, and the editor-side Industry (Overall) toggle handler 0x004cf430 through 0x00434f20. So while the fixed 0x6a70..0x73c0 candidate-availability block is now well grounded as bundled map/save source data, a direct bulk-import path from that block into the live runtime collection [state+0x66b2] is still not grounded by the current disassembly notes. That candidate-side table now has a grounded fixed record layout too: each entry is a 0x22-byte blob with a zero-terminated candidate-name slot at [entry+0x00..+0x1d] and one trailing availability dword at [entry+0x1e], read through 0x00434ea0 and mirrored later into [candidate+0x7ac]. The same scenario state keeps a locomotive-side sibling collection at [state+0x66b6], read through 0x00435030 and updated through 0x004350b0, which is now the shared named locomotive-availability lane beneath the Locomotives editor page and the startup-side locomotive seeding branches. That locomotive-side table is the same pattern at a larger width: each entry is a 0x41-byte blob with a zero-terminated locomotive-name slot at [entry+0x00..+0x3c] and one trailing availability dword at [entry+0x3d], later mirrored into [loco+0x7b]. Both override dwords now read most safely as simple availability bits rather than wider mode enums. That 319 lane is no longer just a shell-state placeholder: its primary grounded work is still the chairman-profile pair world_seed_default_chairman_profile_slots 0x004377a0 plus world_build_chairman_profile_slot_records 0x00437220, which seed the 16 selector bytes at [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], the direct campaign-designated bit [+0x66de] through control 0x5b6e, and the inverse of the paired metadata byte [+0x66f3] through control 0x5b74. The resource-side anchor is now explicit too: editorDetail.win carries localized ids 3160/3161 Campaign Scenario and If checked, this map will be reserved as a campaign scenario. inside the control record rooted at 0x5b6e, so [+0x66de] is now the grounded campaign-scenario flag rather than an anonymous metadata boolean. map_editor_scenario_metadata_panel_refresh_briefing_mode 0x004ca670 now bounds the single-player versus multiplayer briefing switch by flipping selector 0x621f50, publishing localized headings 1491 and 3586, and refreshing the two briefing texts from [state+0x4f30] and [+0x5ae9]. The companion dispatcher 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 49-entry static rule table at 0x005f3ab0, counts enabled flags from [0x006cec78+0x4a7f], and publishes the Special Conditions In Effect summary from localized id 1053. The same page now has a bounded live dispatcher too: map_editor_scenario_special_conditions_panel_handle_message 0x004cb8e0 handles both bulk selection controls and direct row-state changes, commits them back into [0x006cec78+0x4a7f], and then re-enters the panel constructor to refresh the summary. That table is no longer just a raw id run; it now clearly includes the finance and construction restrictions 2535..2563, plus later editor toggles such as Use Bio-Accelerator Cars, Disable Cargo Economy, Disable Train Crashes, Disable Train Crashes AND Breakdowns, and AI Ignore Territories At Startup. The neighboring available-chairman page is tighter too. map_editor_available_chairman_panel_construct 0x004ca540 now bounds the shell-side owner for the 40-entry persona-availability surface under 0x5aa0..0x5b03: it walks the same persona table family at 0x005f2d28, publishes one localized chairman-name row per profile, counts enabled availability bytes from [0x006cec78+0x6987..], and emits the summary %1 out of %2 are selected. from localized id 1035. The live state owner beside it is now grounded as well: map_editor_available_chairman_panel_handle_message 0x004cb6f0 handles three bulk-selection controls 0x5aa1..0x5aa3 by rewriting that same availability-byte array from preset bytes embedded in the persona table, and it also commits direct per-row toggle changes from 0x5aaa..0x5b03 back into [state+0x6987..] before refreshing the page. So the editor lane now has three distinct scenario-setup slices rather than one chairman-only blob: chairman slots, scenario metadata and briefings, plus both a rule-toggle matrix and an available-chairman pool. There is now one adjacent company-side lane too: current neighboring setup flow conditionally enters world_conditionally_seed_named_starting_railroad_companies 0x0047d440 when the Multiplayer preview owner 0x006cd8d8 is absent and either sandbox flag [0x006cec7c+0x82] is set or shell-state flag [0x006cec74+0x14c] is set while editor-map mode [0x006cec74+0x68] is clear. That helper no longer looks like a generic company refresh. It seeds exactly three fixed named railroad-company records from RT3.lng ids 575..577: Missouri Pacific, New York Central, and Grand Trunk Railroad. The first seeded company is tied back to the selected chairman-profile summary and becomes the selected company id. The second railroad is tighter now too: it only receives a chairman link when profile_collection_count_active_chairman_records finds at least two live chairman records, and the helper then binds the zero-based second active chairman through profile_collection_get_nth_active_chairman_record with ordinal 1. The third railroad currently gets no matching chairman-link branch in the grounded setup flow and therefore remains an unchaired named company in the live roster. The shell UI above that setup lane is now tighter as well: shell_company_list_window_construct 0x004c7200 builds a live company-list window over the company collection at 0x0062be10, shell_company_list_window_refresh_rows 0x004c6c30 formats the active companies with localized strings 267..270, and only then conditionally appends one synthetic row id 0x7fff through shell_company_list_format_company_or_start_row 0x004c6b40 so <<Start New Company>> appears as a separate affordance rather than as part of the seeded trio itself. Current shell paging around that same roster is tighter too because the live company collection now has a grounded active-only ordinal helper family: company_collection_count_active_companies 0x00429a50, company_collection_count_active_companies_before_company_id 0x004299f0, and company_collection_get_nth_active_company_id 0x00429990. Those helpers now anchor the “current company among active companies” math used by shell-side detail and picker flows rather than leaving it as anonymous collection glue. shell_company_list_window_handle_message 0x004c6f30 then routes the synthetic row into start_new_company_dialog_open 0x0047d080, whose commit path now grounds through start_new_company_dialog_commit_create_company 0x0047d120. That lower helper unlinks any current chairman-owned company, allocates a fresh company id from the live collection at 0x0062be10, initializes it through 0x00428420, and only then publishes the new selected company. The neighboring compact request helper start_new_company_request_create_company 0x0047d320 does the same fresh-company path from a request block and is already reached from the startup-company branch at 0x00470e48. The immediate sibling shell branch below that roster is still station-oriented: current grounded resource names and handlers put one branch on shell_station_detail_window_construct 0x005068c0, another on shell_station_list_window_construct 0x005074c0, and the subordinate selector helper on shell_station_pick_window_construct 0x00507620. But the broader company-detail ownership question is no longer open. There is now a separately grounded CompanyDetail.win family rooted at shell_company_detail_window_construct 0x004c5540, with shell_company_detail_window_handle_message 0x004c56a0 as its main dispatcher and shell_company_detail_window_refresh_controls 0x004c2ca0 as the shared repopulation pass for the selected-company presentation and tabbed control bands around 0x9476..0x9490. A grounded shell detail-manager caller reaches that constructor at 0x004dde24, the first finance-action layer beneath it is now bounded through shell_company_detail_issue_bond_offer_flow 0x004c3890, shell_company_detail_issue_stock_offer_flow 0x004c3f30, shell_company_detail_buyback_stock_flow 0x004c46d0, and shell_company_detail_change_dividend_rate_flow 0x004c5360, and the first non-finance layer is now bounded too through shell_company_detail_resign_chairmanship_flow 0x004c5a0e, shell_company_detail_bankruptcy_flow 0x004c5b99, the territory-access family rooted at shell_company_detail_refresh_selected_territory_access_summary 0x004c1b60 plus shell_company_detail_buy_territory_access_rights_flow 0x004c5fc9, backed by company_clear_selected_chairman_if_current_profile 0x00428a10, company_declare_bankruptcy_and_halve_bond_debt 0x00425a90, company_has_territory_access_rights 0x00424010, company_set_territory_access_rights_byte 0x00424030, and company_can_purchase_territory_access_rights 0x00426be0, plus the two control-transfer lanes. shell_company_detail_attempt_chairmanship_takeover_flow 0x0050ccc0 now grounds the special chairman's election path: it checks the caller's current stock ownership in the target company, rejects insufficient holdings through localized id 623, rejects recent failed attempts through id 624, and then opens the confirmation under id 625 before seeding the local takeover-election state or packaging the same request through the multiplayer shell transport. The follow-on resolver shell_resolve_chairmanship_takeover_vote_and_commit_outcome 0x0050c940 now closes the single-player election loop too: it walks the active chairman profile collection, computes weighted votes for and against the takeover, compares the affirmative total against half the target-company value, presents the result through shell_present_chairmanship_takeover_vote_outcome_dialog 0x0050c500 in single-player or localized id 3082 in multiplayer, and then either transfers chairmanship through 0x00428a30 or stamps the current year into [company+0x289] as the grounded takeover-cooldown field. shell_company_detail_attempt_merger_flow 0x004ec640 now grounds the merger side too: it rejects empty worlds through id 727, rejects recent failed attempts through id 728, checks the proposed premium against company cash through localized id 3889, and then commits into the resolver family. That merger resolver is now bounded too: shell_resolve_merger_vote_and_commit_outcome 0x004ebd10 walks the active chairman profile collection, computes weighted votes for and against the proposed merger, compares the affirmative total against half the target-company value, presents the result through shell_present_merger_vote_outcome_dialog 0x004eb890 in single-player or localized id 3059 in multiplayer, and then either commits the merger through 0x00427e20 or stamps the current year into [company+0x15f] as the grounded merger-cooldown field. The vote-bias side beneath that resolver is tighter now too: scenario_state_compute_issue_opinion_multiplier 0x00436590 is no longer just an abstract issue table lookup because its merger callsite uses issue id 0x3a, which lines up directly with localized id 726 saying merger votes depend on public attitude toward the management of the two companies. By contrast the broader support-adjusted share-price helper company_compute_public_support_adjusted_share_price_scalar 0x00424fd0 uses issue id 0x37, while the finance-side debt helpers now bound 0x38 and 0x39 separately as the explicit credit-rating and prime-rate lanes. That leaves 0x37 as the broader investor-confidence lane behind equity support, share price, and adjacent governance pressure, with the strongest current text anchors coming from the investor-attitude strings 1217 and 3048/3049 about company or chairman performance rather than from the merger-only management-attitude term. One older local lead is now ruled out too: the 0x460a90 / 0x473620 setup block is the camera-view hotkey family over localized ids 3482..3489 (Select/Assign Camera View 5..8), not issue-opinion infrastructure, so it should no longer be used as evidence for the player-facing meaning of issue 0x37. The editor-side Stock Prices label is also no longer being used as direct evidence here: the 0x4ca980 / 0x4cadf0 panel owns a separate float-tuning block [state+0x0bde..0x0bf6], with [state+0x0bde] merely mirroring [state+0x0be2], so that label belongs to a different settings family than the issue table behind 0x37. A direct shell-resource follow-up now narrows the remaining caption question too: the extracted CompanyDetail.win blob from rt3_2WIN.PK4 contains no plain-English investor or finance caption for this lane, which matches the owner-side read that section-0 is a dynamic 0x947f text widget fed by shell_format_company_governance_and_economy_status_panel 0x004e5cf0 rather than a separate fixed label row. The supporting stat layer is bounded more cleanly now too: the surrounding 0x0b setup in the merger and takeover offer builders is formatter mode rather than a player-facing issue number, while the company-side stat wrapper company_read_year_or_control_transfer_metric_value 0x0042a5d0 now reads as a generic 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, whose grounded tail now also sweeps the live region collection through world_region_refresh_cached_category_totals_and_weight_slots 0x00423d30; id 322 then fronts Calculating Heights.... The master +0x68 flag is no longer just structural: the shell load/save coordinators now use the same flag to force the editor-map .gmp family, so current evidence treats it as the broader editor-map mode above those later setup branches rather than an unnamed generic toggle. That worker is no longer one opaque building bucket: current grounded categories split into House, a weighted region-profile family surfaced through the Industry Weightings stats path, and a third branch whose low-level fallback token is Commercial but whose aligned stats label is City Support. The same placement-commit gate beneath it, world_region_validate_and_commit_candidate_placement 0x00422a70, is also corroborated by the separate world-side randomized batch helper world_try_place_random_structure_batch_from_compact_record 0x00430270, which retries placements around one compact center/radius record rather than the ordinary per-region demand deficits. That batch placer now sits under a wider compact runtime-effect dispatcher, world_apply_compact_runtime_effect_record_to_resolved_targets 0x00431b20, so the world-side branch is no longer just “another caller near 0x43051e” but one real effect family alongside the ordinary region-demand worker. Above that, the live scenario event collection at 0x0062be18 now has a tighter runtime-effect lane too: scenario_runtime_effect_record_service_and_dispatch_linked_compact_effects 0x004323a0 services one live runtime-effect record, dispatches its linked compact effects through 0x00431b20, and can synthesize follow-on records through scenario_runtime_effect_record_build_followon_effect_from_compact_record_and_targets 0x00430b50, which in turn allocates new live records through scenario_event_collection_allocate_runtime_effect_record_from_compact_payload 0x00432ea0. Above that, scenario_event_collection_service_runtime_effect_records_for_trigger_kind 0x00432f40 now bounds the collection-wide loop that services those live runtime-effect records for one trigger kind. That trigger split is tighter now too: recurring simulation maintenance drives kinds 1, 0, 3, and 2; the neighboring route-style follow-on drives 5 and 4; startup-company and named-railroad creation branches drive 7; kind 6 is now bounded as a mixed post-change family spanning the placed-structure post-create tail, one build-version-gated company-startup or roster-refresh tail, and the route-entry post-change sweep on 0x006cfca8; one world-entry-side one-shot gate drives 8 and then clears shell-profile latch [0x006cec7c+0x97]; the briefing-text query lane is kind 9; and the collection dirty latch still forces the internal rerun at kind 0x0a. That moves this branch out of the “isolated world-side placement oddity” bucket and into a real scenario-runtime effect pipeline with a mostly bounded trigger-kind family. The same lower helper also reappears later on a slower simulation-side cadence with scale 1/12, so it no longer looks like one-time setup glue only. The actual game-speed control family remains separate, rooted at world_set_game_speed_mode 0x00434680, world_adjust_game_speed_mode_delta 0x00434850, and world_toggle_pause_or_restore_game_speed 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. The category side of that state is now tighter too: the shared helper 0x0044bd10 quantizes the staged world coordinates into the current cell, resolves the mixed byte-or-word region id from [world+0x212d], looks up the owning city-or-region entry through 0x0062bae0, and returns [entry+0x272] with fallback 5; the StationPlace world-surface branches at 0x00508b80, 0x00508d59, and 0x0050a4e6 use that result directly to refresh the current selection category latch at 0x00622af0. 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, and the deeper shared bulldoze helper at 0x0044b160. That helper is no longer just a vague proximity scan: it validates the active company unless editor mode is active, emits the exact RT3.lng bulldoze rejection ladder 419..424, reads company cash through 0x0042a5d0, debits approved bulldoze cost through 0x0042a080, and then scans nearby route entries, linked structures, city-or-region records, route blockers, and placed structures before dispatching the selected delete branch through 0x004937f0, 0x004941a0, 0x0048abf0, or the surrounding placed-structure virtual slot +0x58. That makes the TrackLay Bulldoze mode tighter than before: the tool-side mode latch at 0x00622b0c == 0x40 is only the front-end selector, while the actual world-side bulldoze choice and failure policy sits under 0x0044b160 and is reused by neighboring world-surface callers beyond TrackLay itself. 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: current evidence grounds the shell-controller-backed input and frame path as the only coordinator after world entry; no separate outer gameplay loop or gameplay-only input object is grounded yet. The new setup-pipeline evidence also points the same way: 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, the adjacent tool-window strip now grounded as Bulldoze.win, ChangeHeight.win, ChangeTrees.win, PaintRegion.win, PaintSound.win, PaintTerrain.win, PaintTerritory.win, and StockBuy.win, and now the shell-side Trainbuy.win singleton too. That train-buy family is no longer just an unnamed probe pair either: the opener path is now grounded under the same shell-owned cadence through shell_can_open_trainbuy_window_or_warn and shell_open_or_focus_trainbuy_window, and its current family semantics already extend beyond a bare locomotive picker into selected-train upgrade summary and route-edit affordances. The selected-train side is tighter now too: we have explicit query helpers for the selected train record, id, validity, and company ownership, plus one explicit ownership-mismatch warning modal. That same pass also clarified one boundary we should not conflate: the neighboring shell family rooted at 0x006d3b20 is now grounded separately as TrainDetail.win. It reuses the same selected-train context and some of the same helpers, but it is not the same Trainbuy.win singleton family. The TrainDetail.win side now has its own constructor, opener, refresh path, and message owner above the broader train-command strip. Its inner 0xcb strip is tighter now too: one bounded branch is the selected-train engine-replacement or trainbuy handoff lane using warning ids 593/594, and another is the selected-train retirement lane using 595/596/597 with either a local teardown path or multiplayer opcode 0x37. The remaining train-command family is narrower too: the shared 0x33-stride helper trio at 0x004b2f00, 0x004b3000, and 0x004b3160 now looks like a real train route-stop or waypoint list rather than a generic row buffer, and route-entry flag byte +0x28 now has one grounded top-level split: sign bit clear entries are the live placed-structure-backed family, while sign bit set entries use the direct route-node payload side. The helper train_route_list_count_live_site_reference_entries 0x004b2b80 now counts the first family explicitly. One deeper lower-bit result is grounded too: both train_route_list_insert_staged_entry_at_index and the auxiliary finalize helper train_finalize_aux_route_entry_buffer_preserving_subflags 0x004a94b0 explicitly preserve bits 0x40, 0x20, and 0x10 in the same flag byte during route-entry rewrites. Those bits are also no longer copy-only: the neighboring shell helper shell_building_detail_refresh_flagged_service_capability_rows 0x004b9a20 now consumes them to restyle the BuildingDetail.win row bands 0x7d07..0x7d1c and 0x7f58..0x801f. The exact player-facing labels for those rows are still open, but the subflags now have one real shell-side consumer instead of only preservation logic. The broader BuildingDetail.win refresh family is tighter too: shell_building_detail_refresh_subject_cargo_and_service_rows 0x004ba3d0 now clearly owns the selected subject rows around 0x7d06, 0x7d96.., and 0x7d0e, resolving ordinary ids through the live candidate collection and the special express-side ids through the embedded AnyCargo.imb, AnyFreight.imb, and PassMail.imb paths. The first fixed triplet is now table-grounded instead of only inferred: 0x00621df8 seeds the short-label controls 0x7dc8..0x7dca with RT3.lng 494..496 Any Cargo, Any Freight, and Any Express, while 0x00621e10 seeds the adjacent 0x7e90..0x7e92 icon-name triplet with AnyCargo, AnyFreight, and PassMail before %1.imb formatting. RT3.lng also tightens the longer popup side now: 0x00621e04 feeds the first clickable selector triplet 0x7f58..0x7f5a with 494/497/498, so the help text there is Any Cargo, Any Freight\n(Freight is everything but Passengers, Mail, and Troops), and Any Express\n(Express is Passengers, Mail, and Troops). The sibling special service rows still align to Dining Car and Caboose. The extracted BuildingDetail.win blob now sharpens the resource boundary too: its embedded text table is currently sparse rather than rich, exposing the help line for 0x7d01, repeated BuildingDetail.imb asset strings, and one standalone caption entry Cargo. That makes Cargo the strongest current resource-side anchor for the row header around 0x7d06. The ordinary deeper rows are tighter now too: they do not look like hidden caption-table entries, but like live candidate-derived rows. The current path validates each ordinary id through indexed_collection_entry_id_is_live 0x00517d40, resolves the concrete candidate record through indexed_collection_resolve_live_entry_by_id 0x00518140, and then reuses candidate field [record+0x04] as one shared stem for both the row asset %s.imb path and the neighboring display-label lookup through localization_lookup_display_label_by_stem_or_fallback 0x0051c920. That lookup is now bounded too: it scans the static stem table at 0x006243c8, already grounding entries such as Alcohol, Aluminum Mill, Automobiles, Bauxite, and Big Boy against RT3.lng 3202..3220, and only falls back to localized id 3866 when no table entry matches before the fixed 0x384..0x386 express-side triplet takes over. One neighboring candidate-side helper is tighter now too: structure_candidate_query_route_style_or_local_availability_metric 0x0041e650 shares the same route-style byte at [candidate+0x46], returning the cached local float at [candidate+0x5a] for ordinary candidates but switching route-style rows to one normalized count over the world-side route-link collection 0x006ada90 keyed by candidate class [candidate+0x3e]. That collection is tighter now too: it is constructed during world bring-up by placed_structure_route_link_collection_construct 0x00468110, and current grounded creation flow through placed_structure_route_link_allocate_site_pair_for_candidate_class 0x00467f50 seeds class byte +0x10, a masked initial state template, and the strongest current creation-side site-pair fields at +0x0c and +0x0e before placed_structure_route_link_attach_site_owner 0x00467eb0 links the new route-link record into the placed-structure-owned chain at [site+0x272]. The owner-side split is tighter now too: route-link field +0x08 is the separate route-node-style owner anchor used by placed_structure_route_link_attach_route_node_owner 0x00467f20, while +0x0a/+0x0c/+0x0e now read as the site-reference triple matched by placed_structure_route_link_collection_remove_links_touching_site_id 0x004681f0. Creation flow now sharpens that further: +0x0c is the strongest current candidate for the stable first-site field seeded before owner attachment, +0x0a is the mutable owner-site anchor installed by the attach helper, and +0x0e is the stable second-site field. One more split is tighter now too: placed_structure_route_link_recompute_endpoint_pair_state 0x00467c30 currently uses +0x0a and +0x0e as the active endpoint site pair while recomputing state byte +0x12; +0x0c is still not directly read there. The family also has a clearer release and refresh side now: placed_structure_route_link_release_and_detach 0x004680b0 rolls back the class counters and then tails into placed_structure_route_link_detach_current_owner_chain 0x00467df0, while placed_structure_route_link_collection_recompute_all_endpoint_pair_state 0x004682c0 explicitly reruns the per-record endpoint-pair reconciler across the whole live route-link collection. One layer above that, placed_structure_route_link_rebuild_route_style_grid_counters_and_endpoint_state 0x00468300 now looks like the full-family refresh owner: it clears three route-style class lanes in the world-grid tables rooted at [0x0062c120+0x2129], then clears bit 0x2 across the live route-link records and reruns the endpoint-pair reconciler. That now lines up with the visible shell split: non-route candidates keep the richer local metric and price lane, while route-style candidates use one world-side route-link family instead. The emission side is tighter now too: placed_structure_try_emit_best_route_style_peer_link_for_candidate_class 0x0040fef0 scans the live placed-structure collection for one best peer site by class-specific weight, distance window, and type gate, then only creates a new route-link through placed_structure_route_link_allocate_site_pair_for_candidate_class 0x00467f50 when placed_structure_endpoint_pair_has_shared_route_entry_key 0x0040fbe0 says the chosen site pair does not already share a route-entry key. One layer above that, placed_structure_rebuild_route_style_candidate_scores_and_peer_links 0x004101e0 now reads as the broader per-site owner of this lane: it computes per-class route-style score scalars from local site state and scenario multipliers, drives the first three route-style emission attempts, and then continues into a larger descriptor-driven scoring phase. Inside that larger pass, placed_structure_accumulate_candidate_metric_or_emit_route_style_peer_link 0x0042cab0 now cleanly shows the split between ordinary candidates, which add directly into the local route-style grid lane at [site+candidate*4+0x103], and remapped route-style candidates, which re-enter the peer-link emitter. One layer above that, the broader post-create or post-edit site rebuild placed_structure_finalize_creation_or_rebuild_local_runtime_state 0x0040ef10 conditionally re-enters 0x004101e0 with stack flag 1 when its local latch at [site+0x29e] stays clear, so the route-style lane is no longer floating under an unnamed single-site caller. The placement side is tighter now too: the direct constructor placed_structure_collection_allocate_and_construct_entry 0x004134d0 is the shared allocator immediately beneath the current placement-side callers before they hand the new site into 0x0040ef10, and the lower constructor placed_structure_construct_entry_from_candidate_and_world_args 0x0040f6d0 now bounds the actual field-seeding layer beneath that allocator. The old unresolved higher placement chooser is bounded more cleanly now too: the 0x00403ed5 and 0x0040446b direct-placement commits sit inside one larger helper, city_connection_try_build_route_with_optional_direct_site_placement 0x00402cb0. That shared heavy builder is now the common target of the compact wrapper 0x00404640, the peer-route candidate builder 0x004046a0, the region-entry pair wrapper city_connection_try_build_route_between_region_entry_pair 0x00404c60, and the direct retry paths inside simulation_try_select_and_publish_company_start_or_city_connection_news 0x00404ce0. Internally it now has three bounded lanes: an early route-entry search or synthesis attempt through route_entry_collection_try_build_path_between_optional_endpoint_entries 0x004a01a0, a single-endpoint direct-placement lane that scans Maintenance and ServiceTower candidates and commits through 0x00403ed5 -> 0x004134d0 -> 0x0040ef10, and a later paired-endpoint fallback lane that seeds two endpoint candidates from the same stem family, walks a temporary route-entry list, and commits through 0x0040446b -> 0x004134d0 -> 0x0040ef10. That early lane can now be described more concretely: it can reuse supplied route-entry endpoints, synthesize a missing leading endpoint from the caller's coordinates, seed the route-store builder-state block, and then hand off to the deeper path-search core without placing a new site. The previously vague side family at 0x006cfcb4 is tighter too: current evidence now bounds it as a small auxiliary route-entry tracker collection with an allocator at 0x004a42b0, a refcount or destroy path at 0x004a4340, a direct route-entry group-id setter at 0x00489f80, an endpoint-membership probe at 0x00494ed0, a boolean-latch refresh or owner-notify path at 0x00494fb0, and a two-endpoint merge or bind helper at 0x00494f00. One smaller constructor-side ownership split is tighter now too: the cached u16 chain fields [site+0x26e], [site+0x270], and [site+0x383] are no longer free-floating. Constructor-side helper 0x0041f7e0 prepends one new peer into that chain by storing the old head from [this+0x383] into [peer+0x270] and then replacing [this+0x383] with the peer's own placed-structure id [peer+0x2a4]; the direct resolver 0x0041f810 turns the cached head id back into one live record through 0x0062b26c; and the removal-side companion 0x0041f850 removes one peer from the same chain before clearing [peer+0x26e/+0x270]. That caller split is now strong enough to treat this as one cached single-link or predecessor-chain family beneath placed-structure construction and rebuild rather than as unrelated scratch words. That bind side is tighter now too: the trackers group route entries only when a route-key-like value from 0x0048aa70, the route-entry signature word +0x22e, and the boolean latch derived from byte +0x44 all agree. The deeper handoff under that lane is no longer anonymous either: route_entry_collection_search_path_between_entry_or_coord_endpoints 0x0049d380 is now bounded as the internal search core that runs the first candidate sweep, quality gates, and the later route-extension fallbacks before returning one resolved route-entry id or -1. The first sweep now has a bounded owner at 0x0049bd40, and the two later fallback helpers are bounded as the route-entry point-window coverage query 0x00494cb0 and the frontier-extension helper 0x0049c900. The math side is bounded more cleanly now too: the family reuses math_measure_float_xy_pair_distance 0x0051db80 for its direct point-to-point scalar, math_compute_quadrant_adjusted_heading_angle_from_xy_pair 0x004952f0 for heading-angle construction, math_normalize_subtracted_angle_delta_and_report_wrap 0x004953c0 for wrapped angle-delta checks, and math_abs_double_with_crt_special_case_handling 0x005a152e for the absolute-value side of the quality gates. Current evidence also bounds the threshold shape a little more tightly: the initial sweep and later extension path both reuse one signed angle-bias term +/-0.181000038854627, and the first sweep switches between a looser 1.4 and stricter 1.8 quality multiplier depending on route-policy byte 4 or the broader display-runtime preference [0x006cec78+0x4c74], already grounded elsewhere as Auto-Show Grade During Track Lay. The small policy-byte semantics are still not fully closed, but current evidence is tighter than before. Literal byte 1 is now the strongest current match for direct linked-site endpoint-anchor creation or replacement, because the linked-site constructor and neighboring repair branches around 0x00480463, 0x00480a77, and 0x00480b69 all feed that byte into 0x00493cf0 before rebinding one chosen route-entry anchor through 0x0048abc0. Literal byte 2 now looks broader: the later world-side caller at 0x00480cd0 and the linked-site refresh helper placed_structure_refresh_linked_site_display_name_and_route_anchor 0x00480bb0 both reach 0x004a01a0 with both optional endpoint-entry ids unset and that byte, so the strongest current read is a full linked-site route-anchor rebuild between optional endpoint entries rather than the narrower direct creation lane. The TrackLay side now gives one tighter user-facing anchor too: the live mode field 0x00622b0c is already grounded as Lay single track. 0x1 versus Lay double track. 0x4, and the small mapper 0x004955b0 collapses that state into the endpoint-policy bytes later passed to 0x00493cf0, so the strongest current read is policy 1 = single-track endpoint synthesis and policy 4 = double-track endpoint synthesis. Bytes 1/2 are still the ones that enable the auxiliary tracker lane in 0x004a01a0, while byte 4 now reads more narrowly as the larger company-side endpoint-synthesis charge inside 0x00493cf0, because that helper feeds -1 versus -2 into the saturating company counter helper 0x00423ec0 on [company+0x7680] rather than skipping the company branch entirely. That counter is tighter now too: nearby company initialization seeds it to 50 when scenario byte 0x4aaf is enabled and to sentinel -1 otherwise, while the companion getter 0x004240a0 returns either the live counter or fixed fallback 29999. Current language-table correlation also gives 0x4aaf a stronger player-facing meaning: it is the live gate behind Company track laying is limited... and the event variable label Company Track Pieces Buildable. So the current strongest read is available track-laying capacity, not an abstract company route-budget. That site-side helper also closes one adjacent ownership gap: beneath placed_structure_finalize_creation_or_rebuild_local_runtime_state 0x0040ef10, it rebuilds one linked site's route-entry anchor and display-name buffer. That path is tighter now than just “bind anchor then touch 0x006cfcb4”: after the literal-policy-2 rebuild succeeds it re-enters aux_route_entry_tracker_collection_refresh_route_entry_group_membership 0x004a45f0, which can now be described more concretely. Its early prepass at 0x004a4380 can split one mismatching adjacent subchain into a fresh tracker group; its later helper at 0x004a4ce0 can transfer one compatible adjacent chain between neighboring groups; and the repair-side helper at 0x004a4ff0 can reseed a whole route-entry component into a fresh tracker when the old group id is missing or invalid. The regrouping pass also still rewrites compatible endpoint slots through 0x004950f0 and refreshes one nearby cached-match payload band through 0x00495020 before the helper resumes the name-buffer work. The remaining display-name side still matches the earlier grounded text family: copy the resolved city name when available, append civic suffixes Township, New, Modern, or Renaissance, append Service Tower or Maintenance Facility on the linked-instance class branches, and otherwise fall back through the older Junction..Center and Anytown text families. The higher owner-refresh side of that same tracker family is tighter now too. The reusable gate at 0x004a4c00 no longer looks like a stray predicate: it explicitly requires both route-entry trackers to keep matching cached fields +0x18/+0x1c/+0x1d/+0x1e and both route entries to keep their special side fields +0x20e/+0x222 unset before adjacent-chain transfer is allowed. The collection-wide traversal sweep at 0x004a5fc0 is bounded now as the connected-component refresh owner over tracker field +0x0c, with a temporary queue at [this+0x94] and direct fallback into the reseed helper 0x004a4ff0 whenever one neighboring route entry has lost valid tracker ownership. Above both of those sits aux_route_entry_tracker_collection_refresh_owner_adjacent_compatible_group_links 0x004a6360, which now reads as the owner-side latch-change refresher invoked from 0x00494fb0: it starts from one owner route-entry id, confirms both bound endpoint entries agree on the boolean class state implied by route-entry byte +0x44, and then probes both endpoint sides for adjacent route-entry groups that can be absorbed through the 0x004a4c00 -> 0x004a4ce0 gate-and-transfer pair. The sibling query side is bounded now too: aux_route_entry_tracker_collection_query_component_label_by_tracker_id 0x004a6320 is the dirty-aware accessor for tracker field +0x0c, while aux_route_entry_tracker_dispatch_route_entry_pair_metric_query 0x004a65b0 is the remaining mode-switched lower metric dispatcher beneath the heavier chooser at 0x004a6630, forwarding fixed route-entry-pair candidate sets into either 0x004a5280 or 0x004a5900 depending on the shared hundredths-scaled build-version query runtime_query_hundredths_scaled_build_version 0x00482e00 over 0x006cec74. The current caller thresholds >= 0x67, >= 0x68, >= 0x69, and >= 0x6a now line up with executable build values 1.03, 1.04, 1.05, and 1.06, and the version source itself can come from the multiplayer companion path as well as the local executable, so this split is no longer best-read as a time- or era-side cutover at all. It now reads more cleanly as a pre-1.03 versus 1.03+ route-metric compatibility dispatcher. That lower split is tighter now too: 0x004a5280 is the weighted recursive branch with heuristic ordering, per-tracker best-cost cache 0x006cfcac, and prune threshold 0x006cfcb0, while 0x004a5900 is the alternate recursive neighbor-walk branch that stays within compatible component labels through 0x004a62c0 and accumulates step and mismatch penalties over route-entry links +0x206/+0x20a/+0x20e. Above both of them, aux_route_entry_tracker_query_best_route_entry_pair_metric_with_endpoint_fallbacks 0x004a6630 is now bounded as the real chooser: direct fixed-pair query when both entries pass 0x0048b870, otherwise endpoint-pair fallback across the two tracker groups. The adjacent route-style rebuild side is tighter now too: the same build-version family reaches placed_structure_rebuild_route_style_candidate_scores_and_peer_links 0x004101e0, where build 1.04+ keeps one Recycling Plant stem-specific compatibility branch alive and build 1.05+ skips one older descriptor-side attenuation fallback. There is also one neighboring world-side compatibility lane now bounded below the same family: placed_structure_collect_connected_component_tile_bounds_with_version_gate 0x004160c0 skips one older recursive component-bounds walk through 0x00415f20 on build 1.03+ when scenario field [0x006cec78+0x46c38] is already active. The wrapper above that path is bounded now too: placed_structure_map_tile_range_to_connected_component_records_with_optional_bounds_refresh 0x00416170 walks the caller rectangle, maps tile keys into the component table rooted at 0x0062ba7c, and only re-enters 0x004160c0 when the current owner still has no cached bounds and the local world or scenario suppressors stay clear. The higher neighboring raster side is tighter too. world_grid_refresh_projected_rect_sample_band_and_flag_mask 0x00418610 is the shared projected-rectangle helper above world_grid_refresh_flagged_region_float_extrema_and_mean 0x00415020: it refreshes the temporary sample band at 0x0062b7d0, publishes the surviving rectangle through 0x0044d410, and on the single-sample path re-enters world_grid_toggle_flagged_mask_bit0_for_nonsentinel_rect_samples 0x004185a0 to flip mask bit 0x01 for the corresponding non-sentinel cells. Current grounded callers for 0x00418610 are the neighboring placed-structure local-runtime helper 0x00418be0 and the heavier placement validator 0x004197e0, so this adjacent family now reads more like projected placement or local raster prep than an unowned generic world-grid scan. One neighboring caller into the same height-support band is tighter now too: the world-side branch at 0x00419070..0x004190f0 walks one admitted local window, dispatches the acceptance-gated relaxer 0x0044d6e0 once per cell with a one-cell radius and no immediate tail refresh, and only after that outer loop completes re-enters 0x0044d410 on the full surviving rectangle. The higher owner split is tighter now too. placed_structure_build_local_runtime_record_from_candidate_stem_and_projected_scratch 0x00418be0 is the broader construction or rebuild lane: resolve one candidate id from a stem, build projected scratch through 0x00416ec0, then publish the projected rectangle and validate its side windows through placed_structure_publish_projected_runtime_rect_globals_and_validate_side_windows 0x00416620. That publish pass is bounded now too: it stages 0x0062b308/0x0062b30c/0x0062b310, validates the rectangle against route-entry coverage through route_entry_collection_query_rect_window_passes_entry_type_gate 0x00494240, can branch into the special projected-slot picker placed_structure_try_select_projected_rect_profile_slot 0x00415570, and refreshes the compact per-cell side tables through world_grid_refresh_projected_rect_surface_and_region_byte_tables 0x00414e10 before the finished scratch is copied into one queued runtime record and the new record re-enters 0x00416170 when its rectangle is valid. The smaller sibling 0x00419200 is now bounded beneath that same projected-rectangle family too: it is the tiny getter over the temporary dword cell-value bank at 0x0062b300, flattening one caller cell through live world width [0x0062c120+0x2155] and returning the corresponding dword when the bank exists, else 0. Current grounded caller is the later world-side branch at 0x0048af99. The smaller sibling placed_structure_clone_template_local_runtime_record_for_subject_and_refresh_component_bounds 0x00418a60 now reads as the current-subject clone path above the same connected-component and mask-refresh helpers, returning the cloned local runtime record later stored into [site+0x24e] by placed_structure_refresh_cloned_local_runtime_record_from_current_candidate_stem 0x0040e450. The higher wrapper above that clone path is bounded now too: placed_structure_collection_refresh_local_runtime_records_and_position_scalars 0x004133b0 first drains the temporary site-id queue rooted at 0x0062ba64/0x0062ba6c/0x0062ba70 through placed_structure_local_runtime_site_id_queue_count 0x00414480 and placed_structure_local_runtime_site_id_queue_pop_next 0x00413f50, rebuilding one cloned local-runtime record per queued placed structure through 0x0040e450, and only then sweeps all live placed structures through the side refresh helper placed_structure_refresh_local_runtime_position_triplet_and_linked_anchor_followon 0x0040ee10. The constructor or ownership split beneath that family is tighter now too. The shared allocator placed_structure_collection_allocate_and_construct_entry 0x004134d0 no longer just reaches an anonymous 0x3e1-byte scratch object: it first constructs one concrete placed-structure specialization through placed_structure_construct_concrete_specialization_vtable_5c8c50 0x0040c950, which calls 0x0045b680 to seed the common base table 0x005cb4c0, clear the derived field band [this+0x23a..+0x26a], and re-enter the older base initializer 0x00455610, then installs the specialization table 0x005c8c50. The paired cleanup path at 0x0040c970 now reads like the matching teardown thunk: it briefly reinstalls 0x005c8c50, then immediately demotes the record back to the base table through 0x0045b040 -> 0x00455650 before the stack object is freed or unwound. The corresponding serializer entry 0x0040c980 is equally tight now: it simply tails into 0x0045b560, which first re-enters the base serializer 0x004559d0 and then emits the derived payload bracketed by tags 0x5dc1 and 0x5dc2 over [this+0x23e], [this+0x242], [this+0x246], [this+0x24e], and [this+0x252]. One nearby string clue is useful but narrower than it first looked. The specialization table at 0x005c8c50 is immediately followed by RadioStation and Radio Station, but the local member method 0x0040ce60 now shows why: it compares site stem [this+0x3ae] against Radio Station, canonicalizes that stem to RadioStation on match, and then re-enters 0x0040cd70 plus 0x0045c150. So those adjacent strings ground one stem-normalization lane inside the specialization, not the specialization name by themselves. The small virtual-slot and cached-id side is tighter now too. The same 0x005c8c50 table carries three literal-false stubs 0x0040cc10/0x0040cc20/0x0040cc30, one literal-true stub 0x0040ccc0, and the narrower linked-site-id presence predicate 0x0040ccb0, which simply returns whether [this+0x2a8] is nonzero. Beneath the stem-normalization path, 0x0040cd70 is now bounded as the common cached source/candidate resolver: it clears [this+0x3cc] and [this+0x3d0], scans source collection 0x0062b2fc for a stem match against [this+0x3ae], stores the matched source id into [this+0x3cc] plus the linked candidate/profile id from [source+0x173] into [this+0x3d0], and when no match exists formats localized id 0x00ad through 0x0051e980 with the current stem buffer. The two tiny followers 0x0040cec0 and 0x0040cee0 then resolve those cached ids back into concrete source and candidate records through 0x0062b2fc and 0x0062b268 respectively. The derived payload and transient family under that same table is tighter now too. 0x0045c150 is the clear payload-loader counterpart to 0x0045b560: it reinitializes the derived field band, opens the 0x5dc1/0x5dc2 payload bracket, restores the two payload strings into [this+0x23e] and [this+0x242], clears the transient roots [this+0x24e], [this+0x256], [this+0x25a], and [this+0x25e], and then rebuilds follow-on specialization state through 0x0045b5f0 and 0x0045b6f0. The neighboring builder pair is coherent too: 0x0045b210 formats amb_%1_01.wav, allocates a 0x141-byte transient object, stores it at [this+0x24a], and registers it through 0x0052da00, while 0x0045c310 allocates the separate primary transient handle at [this+0x246] from payload strings [this+0x23e] and [this+0x242], then publishes it through 0x00530720 and 0x0052d8a0. The next rebuild layer is tighter now too. 0x0045b5f0 resolves one current world-position tuple through 0x0052e720 -> 0x0051f090 -> 0x00534490, then uses that derived scalar to refresh the ambient-side transient again through 0x0045b210. Above that, 0x0045b6f0 clears the optional handles at [this+0x25a] and [this+0x25e], then probes and materializes a larger named variant family rooted in [this+0x23e] through strings such as %1_, %1_Upgrade1, %1_Anim%2.3dp, %1_Upgrade1Anim%2.3dp, and %1_Upgrade1Light%2.3dp, looping across numbered variants and publishing surviving records through 0x0052d8a0. One higher timed branch is bounded now too: 0x0045baf0 advances the two timer-like fields [this+0x26a] and [this+0x266], gates on nearby world-distance and candidate-side checks, and then formats one output around rnd_%1_%2.wav plus the same anim or light string family before dispatching through 0x00531e50 under owner 0x006d402c. Their release-side companions 0x0045b160 and 0x0045c3c0 tear down those same transient roots and payload strings again, and the recurring service slice 0x0045be50 updates the derived scalar triplet [this+0x22e], [this+0x232], and [this+0x236] before republishing it through 0x00530720. The string literals amb_%1_01.wav, %1_Anim%2.3dp, %1_Upgrade1Anim%2.3dp, %1_Upgrade1Light%2.3dp, and rnd_%1_%2.wav therefore ground the derived band [this+0x23e..+0x26a] as one payload-plus-transient owner family with ambient, animation, light, and random-sound components, rather than more linked-site or route-entry ids. One intermediate transient build layer is bounded now too. 0x0040cf00 first requires creation-mode byte [this+0x3d4] == 1 and live seed handle [this+0x24e], re-enters 0x0045b370(1), derives one scaled float from current local geometry through [this+0x14], [this+0x21], [this+0x3a], and 0x005c8cf4, and then allocates a second transient handle into [this+0x25a] through 0x00475ed0. It follows that with one current world-position resolve through 0x00414450 and 0x0052e720, several local offset-triplet writes through 0x00475010, and four numbered channel updates through 0x00475030 with selector ids 1..4. That is enough to bound it as another specialization-side transient-handle builder beneath the same payload family as 0x0045c310 and 0x0045b210, without yet over-naming the user-facing subtype or effect semantics of the built handle. One adjacent helper block is tighter now too, and it should stay separate from the concrete 0x005c8c50 vtable rather than being folded into it. The small predicates 0x0040cc40/0x0040cc60/0x0040cc80 all follow the same [this+0x173] -> 0x0062b268 chain into one linked candidate/profile record. 0x0040cc40 returns whether candidate subtype byte [candidate+0x32] equals 1, 0x0040cc60 returns raw candidate byte [candidate+0xba], and 0x0040cc80 returns the stricter conjunction subtype == 1 && class == 3 using class byte [candidate+0x8c]. The current grounded caller for all three is world_grid_refresh_projected_rect_sample_band_and_flag_mask 0x00418610, where they derive the two boolean mode inputs for 0x00415020; that makes them a shared candidate-profile helper cluster adjacent to the specialization family, not direct overrides in the 0x005c8c50 table. The neighboring 0x0040ccf0 stays on the same “adjacent but not the same vtable” side of the boundary: it resolves one linked instance through 0x0047de00, follows that instance's vtable +0x80 owner chain, and returns candidate class byte [candidate+0x8c]. Current grounded callers at 0x00480fb5 and 0x004b03ce compare that returned class against 3 and 4, so the current safest note is simply “linked-instance candidate-class reader.” One gated collection-side scan in the same neighborhood is bounded now too. 0x0040cd10 first requires shell latch [0x006cec74+0x1c3] and creation-mode byte [this+0x3d4] == 1, then resolves the current subject's center world-grid cell through 0x00455f60, reads the local site roster count and id list at [cell+0xeb] and [cell+0xef], and resolves each listed placed-structure id through 0x006cec20. Its current grounded caller is the broader collection sweep at 0x00413860, so the strongest current read is a gated center-cell site-roster scan rather than one more direct specialization override. One small neighboring world-grid helper is grounded cleanly enough to keep too. 0x0040ccd0 takes one live world root, one X-like index, and one Y-like index, multiplies the Y-like term by world width [world+0x2145], adds the X-like term, scales the resulting slot by fixed cell stride 0x1d7, and returns the corresponding cell pointer under base [world+0x2129]. Current grounded callers include the placed-structure cargo-service bitset sweep around 0x0042c386 and several world-grid overlay passes in the 0x004525bc..0x00452bb2 range, so that helper is now best read as the shared (x,y) -> world-cell* resolver rather than another object-specific method. The next sibling table at 0x005c9750 is tighter now too, though still not fully decoded. The structural anchor is map_load_city_database 0x00474610: that loader stages bundle tags 0x61a9..0x61ab, iterates one collection, and dispatches each entry through vtable slot +0x44. In 0x005c9750, that same slot resolves into the sibling record family beside 0x0041ab70/0x0041ab80, which is enough to treat the table as the city-database entry family rather than a generic unresolved runtime object. The small load-side slot 0x0041ab70 simply jumps into 0x0045c6f0, which restores two strings into [this+0x32e] and [this+0x332], stages the same 0x61a9/0x61aa/0x61ab tag family, and iterates the child runtime band rooted at [this+0x316]. The one real behavioral slot we recovered there is 0x0041ab80: it refreshes one named handle through owner 0x006d4020, writes the resulting handle into [this+0x1c], queries three base floats through 0x0045c480, and returns one scaled float derived from the first queried component. That method is currently called from later world-side branches at 0x0046e4f7, 0x004aafee, and 0x004ab020. The exact user-facing semantics of the handle and the many constant-return virtuals in the same table are still open, but the family boundary is no longer arbitrary: this is now the current city-database entry vtable cluster, not another placed-structure specialization. One correction matters here too: the lower 0x00455660/0x00455800/0x00455810/0x00455930 helpers are no longer city-only. Local .rdata now shows the same shared slots under both the city-entry table 0x005c9750 and the sibling Infrastructure table 0x005cfd00, whose constructors at 0x0048a240/0x0048a2dc/0x00490a3c all re-enter 0x00455b20, install 0x005cfd00, and seed the same scalar-band family through 0x00455b70 with the literal stem Infrastructure. So the safest current family name for those low helpers is the broader 0x23a runtime-object band rather than city-entry-only. 0x00455800 and 0x00455810 are simply the paired normalized coordinate getters over [this+0x1e2] and [this+0x1ea], which explains why they recur all over the city-side, route-link, and placed-structure placement code. The narrower helper 0x00455660 sits above those getters: it scales the caller-supplied normalized coordinate pair, converts it through 0x006d4024 -> 0x0051f090 -> 0x00534490, adds a caller-supplied integer height bias, optionally rounds that height through 0x005a10d0 when the auxiliary-preview gate 0x00434050 is active, and finally publishes the resulting world-anchor triplet through 0x00530720. One serializer-side sibling is bounded too. 0x00455930 queries two triplet-like scalar bands through 0x0052e720 and 0x0052e880 and writes the resulting six dwords through 0x00531030; its load-side stream counterpart 0x00455870 reads the same six four-byte lanes back through 0x00531150, republishes the first triplet through 0x00530720, republishes the second through 0x0052e8b0, and returns the summed byte count. The tagged load-side mirror 0x004559d0 restores the same [this+0x206/+0x20a/+0x20e] band beneath tags 0x55f1..0x55f3, then dispatches vtable slot +0x4c. The Infrastructure side is tighter now too. The optional child attach helper 0x0048a1e0 allocates and seeds one fresh Infrastructure child and, when the owner already has more than one child, clones the first child's two triplet bands into that new child before attaching it. The looped rebuild 0x0048dd50 then rebuilds the owner-visible Infrastructure children one ordinal at a time, tears down the higher extras above ordinal 5, refreshes cached primary-child slot [this+0x248] when needed, and finishes with the same world-cell and route-side follow-on family around 0x00448a70, 0x00493660, and 0x0048b660. The smaller attach helper 0x00490a3c is now bounded too: it conditionally allocates one Infrastructure child from a caller-supplied payload stem, attaches it to the current owner, and then seeds three caller-supplied position lanes through 0x00539530 and 0x0053a5b0. The direct route-entry side of the same family is no longer anonymous either: 0x0048e140, 0x0048e160, and 0x0048e180 are the three direct resolvers over owner fields [this+0x206/+0x20a/+0x20e] into the live route-entry collection 0x006cfca8. Another shared sibling family is tight enough now too: the real packed-byte-triplet owner is 0x0052e680, and the two local wrappers 0x00455820 and 0x00455840 both force its recursion flag on. 0x00455820 forwards three explicit byte arguments, while 0x00455840 unpacks one packed u24-style dword into three byte lanes first. The downstream setter writes packed byte-triplet lane [this+0x43], defaults that lane to 0x007f7f7f when all three bytes are zero, and when recursion is enabled it walks child list [this+0x75] through 0x00556ef0/0x00556f00 and re-applies the same packed update recursively to every child. The sibling Infrastructure table 0x005cfd00 also still carries three tiny fixed-return slots after the shared formatter thunk 0x00455860: two return literal 0x46, and one returns fixed float 1.25f, so those slots are now bounded as small table constants rather than as missing behavior. One other sibling table is bounded enough now to keep separate too: local .rdata at 0x005c9a60 carries the same shared low 0x23a slots plus table-specific overrides 0x0041f680, 0x0041f720, 0x0041f7b0, 0x0041f7e0, 0x0041f810, and 0x0041f850, with nearby literals (%1) and Marker09. The exact subtype name behind that table is still open, but the behavior split is strong enough: 0x0041f680 first refreshes the current global preview/helper owner through 0x00455de0 and then forwards mode 1 plus handle [this+0x23a] into 0x004cf830; 0x0041f720 formats [this+0x356], publishes the resulting shell text, and conditionally dispatches 0x00452fa0 with action 0x12 when world state [0x0062c120+0x2175] is 0 or 0x15; 0x0041f7b0 publishes one fixed payload and only then jumps to 0x00453510 when that same world state is 0x12. The same table also has a tighter adjacent helper strip now: 0x0041f6a0 is the direct [this+0x37f] -> 0x00517cf0 slot-count query, 0x0041f6b0 is the rounded normalized-coordinate world-scalar query above 0x0044afa0, and that deeper helper is no longer opaque: it first computes one distance-like term from the current cell to global preview-anchor fields [0x0062be68+0x24/+0x1c] through the precomputed radial helper 0x0051dc00, samples the companion float raster [world+0x1605] at the current cell plus two 8-direction rings, keeps the strongest local rise above the center sample, adds one thresholded preview-scalar bias from [0x0062be68+0x20], and then adds 0x32 more when the small global gate 0x0041fff0 passes. That gate itself now reads as a shared shell/preview threshold test: it returns true when [0x006cec74+0x2bb] == 2, or when the same mode dword is merely nonzero and preview scalar [0x0062be68+0x20] exceeds the float threshold at 0x005c9a9c. 0x0041f6e0 resolves the current center world-grid cell and checks one packed u16 token through 0x0042b2d0, and 0x0041f6f0 is the raw byte getter over [this+0x42]. One nearby mode-gated flag reader is bounded too: 0x0041f910 returns literal 1 when shell mode gate 0x004338c0 is inactive or the object class dword [this+0x23e] is nonzero, and only on the class-0 path does it return the same byte [this+0x42]. The release side under that same sibling family is bounded too: 0x00420650 lazily seeds [this+0x317] from shell-profile word [0x006cec78+0x0d] before re-entering 0x00420350, and that body is now bounded as the local scalar refresh over [this+0x31b]: it compares the seeded word against the current shell-profile word, maps the delta through one bounded piecewise float curve, and applies one extra affine adjustment when [this+0x23e] is nonzero. 0x00420670 then frees the optional dynamic payload at [this+0x37f], clears the cached u16 link chain through 0x0041f8d0, and tails into base cleanup 0x00455d20; and the small collection-side wrapper 0x00421700 simply resolves one entry id, re-enters 0x00420670, and erases that id from the owning collection. The city-entry family also now has one tighter helper-object branch. 0x00474030 switches over mode enum 0..10, maps those cases into 0x00475ed0 with selector families 4/0xd/0xe and fixed scalar presets 0.5/0.75/1.0/1.5/2.0, and on success publishes the caller-supplied world triplet through [helper+0x4]. The refresh helper 0x00474260 first reloads payload through 0x00455fc0, then samples the current normalized coordinates plus one world-height scalar from 0x00448bd0, and rebuilds [this+0x23a] through that same mode-selected helper builder using mode [this+0x242]. The surrounding collection-side and teardown helpers are tight enough now too. 0x004743d0 and 0x00474400 are the two release siblings over the same helper field [this+0x23a]: both destroy that helper through 0x00475100 when live and clear the field, but 0x004743d0 tails into the smaller base cleanup 0x00455650, while 0x00474400 tails into the heavier dynamic-payload cleanup 0x00455d20. The small predicate 0x00474430 simply returns 1 unless shell mode gate 0x004338c0 is active, in which case it returns byte [this+0x42]; the exact meaning of that flag byte is still open, but the mode-gated query itself is bounded now. One level higher, 0x00474450 constructs the collection rooted at vtable 0x005ce4a8 with fixed parameters (0,0,0,0x14,0x0a,0,0), and bootstrap caller 0x004487a9 stores that collection into global 0x006cea50. The collection's entry path is also bounded now: 0x004744a0 seeds a stack-local temporary entry through 0x00474110, allocates one 0x250-byte live record, resolves it, constructs it through 0x00474130, and then tears the temporary entry down through 0x004743d0; 0x00474510 resolves one entry id, releases it through 0x00474400, and removes it from the collection. The collection-owned load loop at 0x00474540 sits directly beneath map_load_city_database 0x00474610: it opens the same 0x61a9/0x61aa/0x61ab bracket on the caller-supplied bundle, binds the selected path context, iterates the current collection, dispatches each record through vtable slot +0x40, accumulates the returned byte counts, and tears down the temporary entry after each record. That still leaves broader semantic questions open, but the current static edges around the city-entry family are now largely exhausted. The adjacent scaffolding is bounded too. Base helper 0x00455b20 initializes the shared 0x23a-sized record family by installing base vtable 0x005cb1c0, clearing the scalar bands [+0x206/+0x20a/+0x20e/+0x22e/+0x232], zeroing the seven-dword block [+0x212..+0x22a], and re-entering 0x0052ecd0; that is why it shows up not only in the city-entry temporary constructor 0x00474110, but also in several later object construction paths outside the city family. The city collection itself now has a bounded teardown side too: 0x00474480 is the small release-and-free wrapper for the collection rooted at 0x005ce4a8, and teardown caller 0x004492c3 uses it before freeing the global collection pointer at 0x006cea50. On the load side, 0x00445713's broader setup branch re-enters map_load_city_database 0x00474610 on that same global 0x006cea50 collection. Outside the city-specific branch, the two tiny dispatch wrappers 0x00455a40 and 0x00455a50 are also now bounded as raw vtable-slot helpers: the first jumps through entry slot +0x44, while the second pushes one caller argument into slot +0x40 and then clears the global roots 0x006acd38/0x006acd3c/0x006acd40. Finally, 0x00455a70 is now bounded as the generic current-position triplet publisher that queries 0x0052e720, converts through 0x006d4024 -> 0x0051f090 -> 0x00534490, adds a caller-supplied height bias, optionally rounds under 0x00434050, and publishes through 0x00530720. The temporary-entry constructor and live entry constructor are bounded now too. 0x00474110 is the tiny stack-local initializer: it re-enters shared base init 0x00455b20, clears helper fields [+0x23a] and [+0x242], installs vtable 0x005ce428, and returns. 0x00474130 is the real live-entry constructor: it stores the entry id into [+0x23e], clears the trailing helper payload block [+0x246..+0x24e], stores mode [+0x242], derives one world-height scalar from the supplied coordinate pair through 0x00448bd0, builds helper field [+0x23a] through 0x00474030, and then seeds the remaining default scalar or flag tuple through 0x00455b70 using the fixed defaults at 0x005ce49c/0x005ce4a0/0x005ce4a4. That broader helper is no longer city-specific either: 0x00455b70 is now bounded as the shared scalar-band initializer that clears the same [+0x206/+0x20a/+0x20e/+0x22e/+0x232] family, optionally copies up to three caller-supplied strings into [+0x206/+0x20a/+0x20e], synthesizes one default local token buffer when the middle string is absent, chooses one effective mode string from the third or first input, derives one owner handle or transform token through 0x0051f090 unless the caller suppresses that path, and then seeds the remaining scalar band through 0x0052edf0 and 0x0052e670. The same specialization also now has one tighter UI-facing side. The override trio 0x0040e4e0, 0x0040e880, and 0x0040e9d0 all sit in the same 0x005c8c50 table and reuse the linked-site-capable vtable +0x70 latch together with creation-mode byte [this+0x3d4]. 0x0040e4e0 is the strongest current owner for contextual status text: it branches across linked-peer checks, world-mode fields [0x0062c120+0x2171/+0x2175/+0x2179/+0x2181], current owner state, and candidate or linked-peer display labels, then formats localized ids such as 0x00af, 0x00b0, 0x00b1, 0x00b2, 0x00b3, and 0x0afd before pushing the result through shell presenter 0x00538c70. 0x0040e880 pairs with that publisher on the action side: it first resets the same presenter through the fixed token at 0x005c87a8, then dispatches several world-side follow-ons through 0x00413620, 0x00453510, 0x00452db0, and 0x00452fa0 under the same linked-peer and world-mode gates. 0x0040e9d0 is the narrower query-style formatter: when shell branch [0x006cec74+0x74] is live it formats one localized label with the fixed suffix \nAbsIndex %d, otherwise it can return one company-side owner label through 0x00426b10, and only then falls back to 0x00455860. So the current best read is that this concrete specialization owns both the ambient or animation transient family and one linked-peer status or action UI surface, without yet proving the user-facing subtype name. One smaller subtype hook cluster is tighter now too. The concrete table also carries 0x0040d170 and 0x0040d1b0, both of which resolve the current candidate through cached stem id [this+0x3cc] and then test candidate dword [candidate+0x4b]. When that flag is nonzero, 0x0040d170 tail-calls the primary transient builder 0x0045c310 and 0x0040d1b0 tail-calls the matching release path 0x0045c3c0. The same neighborhood now also gives direct cached-record resolvers instead of more anonymous pointer math: 0x0040d1f0 returns the linked peer from [this+0x2a8] through 0x006cec20, while 0x0040d210 returns the owner-side record from [this+0x276] through 0x0062be10. That makes the specialization-side ownership split cleaner: the 0x005c8c50 family is not only formatting labels and driving side effects, it also has a direct candidate-flag hook for building or dropping the primary transient handle. The last lower side reads are tighter now too. 0x0040e450 first seeds the projected-slot cache through placed_structure_cache_projected_rect_profile_slot_id 0x00414470 before it re-enters 0x00418a60, and the broader stem-based builder at 0x00418be0 now has one named optional side renderer instead of an anonymous callsite: placed_structure_render_local_runtime_overlay_payload_from_projected_bounds 0x00418040. The side refresh split is bounded now too. 0x0040ee10 publishes one local position or scalar triplet through the shared setter 0x00530720, then tails into placed_structure_refresh_linked_site_anchor_position_triplet_for_local_runtime 0x0040e360; that smaller follow-on only runs on the current subtype-1, class-3, linked-site branch, and recomputes one local-runtime triplet from the linked peer's route-entry anchor when that anchor is still live. The heavier sibling above that side refresh is bounded now too: placed_structure_set_world_coords_and_refresh_local_runtime_side_state 0x0040eba0 is the world-coordinate mutation helper that recomputes [site+0x388] and [site+0x38c], rewrites the world-grid owner mapping through 0x0042c9f0 and 0x0042c9a0, updates the subtype-4 proximity-bucket family when needed, rebuilds the same local position or scalar triplet, and then tails into the linked-site anchor follow-on at 0x0040e360. One later caller into that same side-refresh family is bounded now too: 0x00419110 clamps a caller rectangle to the live world bounds, resolves one per-cell bucket chain through the hashed map at [arg0+0x88] and 0x0053dae0, and then re-enters 0x0040eba0 for every bucketed site in that rectangle using the stored per-entry coordinate pair plus two zero flags. Current grounded caller is the edit-side branch at 0x004bc851, immediately after the neighboring nibble and companion-float mutations, so this now looks like a bucket-map-driven local-runtime side-state refresh wrapper rather than another broad site sweep. The sibling policy-1 side is tighter now too. The constructor lane no longer stops at “one linked site id at [site+0x2a8]”: the subtype-1 branch in placed_structure_construct_entry_from_candidate_and_world_args 0x0040f6d0 now clearly allocates that linked record through placed_structure_collection_allocate_and_construct_linked_site_record 0x00481390, whose lower constructor is placed_structure_construct_linked_site_record_from_anchor_and_coords 0x00480210. That lower constructor seeds the linked record's own id and anchor-site id, clears the local route-anchor and display-name fields, projects the anchor footprint into world space, and then either binds an already-covered route entry through 0x00417b40 or falls through into the neighboring policy-1 route-entry synthesis family around 0x00493cf0 before rebinding the chosen route entry through 0x0048abc0. The cleanup side is tighter now too. Linked-site removal now has a bounded owner at placed_structure_collection_remove_linked_site_record 0x004813d0: it resolves the linked record through 0x006cec20, runs the per-record teardown placed_structure_teardown_linked_site_runtime_state_before_removal 0x00480590, removes the live entry from the collection, and only then re-enters the still-bounded company-wide follow-on at 0x00429c10 when the removed record passed the narrower transit-like latch. That per-record teardown is no longer just “clear some scratch fields.” It now clearly clears the route-style scratch lane, clears the five proximity buckets at [site+0x590..0x5b8], detaches or invalidates the current route-entry anchor, frees the three per-site byte arrays at [site+0x24..0x2c], clears this site's indexed byte from the corresponding arrays of later placed-structure records, and then re-enters 0x00436040 with the current site id. That company-side follow-on is no longer just one opaque callback either. It is now bounded as company_collection_refresh_active_company_linked_transit_site_peer_caches 0x00429c10, which walks the active company roster and re-enters company_rebuild_linked_transit_site_peer_cache 0x004093d0 on each company. That per-company fast pass stamps a refresh tick at [company+0x0d3e], clears and repopulates the placed-structure-side cache cells addressed through [site+0x5bd][company_id], marks the eligible linked transit sites for that company, allocates one 0x0d-stride peer table for each eligible site, and fills those peer rows from aux_route_entry_tracker_query_best_route_entry_pair_metric_with_endpoint_fallbacks 0x004a6630. That helper no longer reads as one anonymous route sweep: it either uses the fixed pair directly or falls back across tracker endpoint combinations before returning the winning route-entry id, one route-step count, and one companion mismatch count. The fast cache now reads more cleanly too: peer-record dword +0x05 stores that step count, while float +0x09 stores the normalized continuity share derived from (steps - mismatches) / max(steps, 1), not a raw delta-per-step ratio. The adjacent timed wrapper company_service_linked_transit_site_caches 0x00409720 now shows the cadence too: 0x004093d0 is the shorter-interval refresh, while the older heavier sibling at 0x00407bd0 was only revisited on the longer interval. That heavier sibling is now bounded too: company_rebuild_linked_transit_autoroute_site_score_cache 0x00407bd0 no longer looks like a generic tail refresh. It reuses the fast peer tables, rebuilds candidate-local amount bands plus normalized issue-opinion scales, and then folds the peer-side route metrics back into three per-site cache floats with a cleaner split: +0x12 is the raw surviving site-score total, +0x0e is the continuity-and-step-weighted companion total, and +0x16 is the promoted final site-ranking lane chosen from the strongest grouped candidate bands. That also closes most of the cross-version impact question: the pre-1.03 versus 1.03+ tracker metric split now looks like it mainly perturbs the weighted +0x0e lane and the promoted +0x16 lane, not the raw +0x12 total. That final lane then feeds the neighboring selectors company_select_best_owned_linked_transit_site_by_autoroute_score 0x00408280 and company_build_linked_transit_autoroute_entry 0x00408380. That makes the company-side follow-on read more like a linked-transit autoroute cache family than a generic company maintenance pass. The neighboring reachability gate is tighter now too: company_query_cached_linked_transit_route_anchor_entry_id 0x00401860 caches one company-side route-entry anchor, and placed_structure_is_linked_transit_site_reachable_from_company_route_anchor 0x004801a0 uses that anchor to decide whether a foreign linked transit site can still participate in the current company's fast peer cache. The first direct train-side consumer above that cache family is bounded now too: train_try_append_linked_transit_autoroute_entry 0x00409770. After servicing the owning company's caches, it asks 0x00408380 for one staged 0x33-byte route entry using the train's current anchor site, then either appends that entry through 0x004b3160 and refreshes the new trailing selection through 0x004b2f00, or rotates one existing slot in place when the local two-entry cap has already been reached. So this edge now reaches an actual train-side autoroute append lane rather than stopping at anonymous company-side cache cells. The weighted cache lanes still do not escape that route-choice family directly: this train-side append path only inherits the weighted site and peer choice by calling 0x00408380, not by reading cache +0x0e/+0x16 itself. The train-side follow-on above that seed path is bounded now too. The owning company can count its live roster through company_count_owned_trains 0x004264c0, measure one aggregate linked transit site pressure through company_compute_owned_linked_transit_site_score_total 0x00408f70, and then rebalance that roster through company_balance_linked_transit_train_roster 0x00409950. The aggregate helper no longer reads as a raw sum either: it starts from the site-cache +0x12 totals, converts that into one tentative roster target through year and site-count ladders, and on build 1.03+ adds one special distance-side scaling branch when exactly two eligible linked transit sites survive. Because it consumes +0x12 rather than +0x0e or +0x16, current evidence now says the tracker compatibility split is more important for seeded route choice and ranked site choice than for the final company train-count target itself. The local linked-transit chain is now bounded enough to say that directly: weighted cache lanes feed 0x00408280 -> 0x00408380 -> 0x00409770/0x00409830, while the separate pressure or roster lane feeds 0x00408f70 -> 0x00409950 from raw +0x12. The balancer then applies two age bands to company-owned trains: very old trains are removed when the roster already exceeds target or upgraded when it still needs capacity, while the mid-age band can trigger one narrower upgrade pass. After that it fills any remaining deficit by either packaging multiplayer opcode 0x75 or locally re-entering company_try_add_linked_transit_train_and_publish_news 0x00409830. The two visible news helpers under it are bounded too: 0x00409830 emits RT3.lng 2896 for a newly added train, while company_publish_train_upgrade_news 0x00409300 emits RT3.lng 2897 for the upgrade branch. The subtype-4 sibling side is bounded now too. The nearby-site bucket family now has: placed_structure_append_nearby_transit_site_distance_bucket_entry 0x0047fdb0, placed_structure_remove_site_id_from_proximity_bucket_lists 0x0047dd10, and placed_structure_clear_proximity_bucket_lists 0x0047dcd0, plus the two collection sweeps placed_structure_collection_append_site_into_all_proximity_bucket_lists 0x00481480 and placed_structure_collection_remove_site_id_from_all_proximity_bucket_lists 0x004814c0. Current evidence says those five buckets store (peer site id, distance) pairs for nearby station-or-transit peers, grouped through the five-way classifier at 0x0040d350. The older stream-backed side is bounded too: placed_structure_collection_load_dynamic_side_buffers_from_stream 0x00481430 walks the live placed-structure collection and re-enters placed_structure_load_dynamic_side_buffers_from_stream 0x0047d8e0, which repopulates the route-entry list, the three per-site byte arrays, the five proximity buckets, and the trailing scratch band from the caller-supplied persistence stream. The linked-site route-entry list itself is tighter now too. The refresh or teardown branch at 0x0040e102 re-enters placed_structure_remove_route_entry_key_and_compact 0x0047d810, which removes one matching u16 key from the six-byte list rooted at [site+0x462]/[site+0x466], compacts the surviving entries into a replacement buffer, and decrements the stored route-entry count. The broader company-side owner above these pieces is tighter now too. The periodic service pass company_service_periodic_city_connection_finance_and_linked_transit_lanes 0x004019e0 now reads as the current outer owner for this branch: it sequences the city-connection announcement lanes, the linked-transit train-roster balancer, the acquisition-side sibling company_try_buy_unowned_industry_near_city_and_publish_news 0x004014b0, the annual finance-policy helper company_evaluate_annual_finance_policy_and_publish_news 0x00401c50, and the shorter-versus- longer linked-transit cache refresh tail through 0x004093d0 and 0x00407bd0. That outer pass also has one tighter temporary-state role now: it clears company bytes 0x0d17/0x0d18/0x0d56, mirrors 0x0d17 into scenario field 0x006cec78+0x4c74 only while the earlier route-building side runs, and restores the original scenario value on exit. Current evidence now ties 0x0d17 to the shared preferred-locomotive chooser 0x004078a0: the override is only armed when that helper picks one locomotive whose engine-type dword is 2. That engine-type lane now best reads as electric rather than an unnamed class slot, because the linked approval helper around 0x0041d550 now reads as a real locomotive-era and engine-type policy gate, dispatching the same 0/1/2 field across three scenario-opinion lanes while the local player-facing engine-type family is explicitly Steam / Diesel / Electric. That same gate also now ties the later scenario bytes 0x4c97..0x4c99 back to the editor-side Locomotives page rather than treating them as anonymous availability flags: they are the live All Steam Locos Avail., All Diesel Locos Avail., and All Electric Locos Avail. policy bytes behind 0x004cd680 / 0x004cf0d0. The current logic is also tighter than a plain override tier: a positive engine-family opinion result can carry the gate by itself only while none of those three editor bytes is enabled; once any of them is nonzero, 0x0041d550 instead requires one matching intersection between the record-local family bytes and the enabled editor family bytes. The WhaleL carveout is narrower now too: current data-file correlation ties that stem to the Orca NX462 / WhaleL_NE locomotive family, and it explicitly zeros that positive-opinion result before the later family-availability checks, so it loses the shortcut rather than gaining a special approval path. The same chooser now also has a bounded fallback below it, locomotive_collection_select_best_era_matched_non_electric_fallback_id 0x00461cd0, which explicitly skips engine-type 2 and chooses the lowest-penalty remaining locomotive by era mismatch and approval gates. The route-search side is tighter too: this electric-only override now clearly feeds the first path-sweep branch in 0x0049bd40, forcing the larger 1.8 initial quality multiplier instead of 1.4, which is the same branch otherwise chosen by explicit route-policy byte 4. So the later annual finance helper is reading same-cycle side-channel state from the earlier city-connection and linked-transit branches, not unrelated long-lived finance fields. The inner finance helper is not debt-only either. Current grounded outcomes include bankruptcy news 2881, the debt restructure family 2882..2886, a later share-repurchase headline 2887, and the dividend-side adjustment branch. The main commit verbs under that helper are now grounded too: company_repay_bond_slot_and_compact_debt_table 0x00423d70, company_issue_bond_and_record_terms 0x004275c0, company_repurchase_public_shares_and_reduce_capital 0x004273c0, and company_issue_public_shares_and_raise_capital 0x00427450. The threshold side is tighter now too. The earliest creditor-pressure lane requires scenario mode 0x0c, the bankruptcy toggle [0x006cec78+0x4a8f] to be clear, at least 13 years since [company+0x163], and at least 4 years since founding year [company+0x157]; it then scans the last three years of the derived net-profits and revenue lanes 0x2b and 0x2c, chooses one negative pressure ladder -600000 / -1100000 / -1600000 / -2000000 from the current slot-0x2c bands around 120000 / 230000 / 340000, requires the broader support-adjusted share-price or public-support scalar at least 15 or 20 depending on whether all three sampled years failed, checks the current fuel-cost lane in slot 0x09 against 0.08 times that ladder, and requires the three-year slot-0x2b total to clear one final -60000 gate before it falls into the bankruptcy commit and RT3.lng 2881 headline. The middle debt-capital layer is split more clearly now too. With [+0x4a8b] clear, one annual bond lane first simulates full repayment through company_repay_bond_slot_and_compact_debt_table and then uses the post-repayment cash window with fixed -250000 and -30000 thresholds plus the broader linked-transit train-service latch [company+0x0d56] to decide whether to append one or more 500000 principal, 30-year bonds. The repurchase lane is separate again: when the city-connection announcement-side latch [company+0x0d18] is set, growth setting 2 does not suppress it, and [+0x4a87] is clear, it starts from one 1000-share batch, can replace its default 1.0 factor with one linked-chairman personality scalar, scales that by 1.6 when growth setting 1 is active, and then runs one 800000 stock-value gate plus one support-adjusted-share-price-times-factor-times-1000-times-1.2 affordability gate before the repeated 1000-share buyback commits behind RT3.lng 2887. The ordering above this helper is tighter now too: company_service_periodic_city_connection_finance_and_linked_transit_lanes clears those latches first, runs the city-connection and linked-transit branches, and only then enters the annual finance helper, so these look like same-cycle reaction gates rather than long-lived balance-sheet flags. After the earlier debt or bankruptcy outcomes stay inactive, the later stock-capital lane also has a tighter bounded shape now too: it only opens on build 1.03+, only after the earlier bankruptcy, bond, and repurchase outcomes stay inactive, and with the bond and stock toggles [+0x4a8b] and [+0x4a87] clear, at least two bond slots live, and at least one year since founding. It derives one issue batch from outstanding shares rounded down to 1000-share lots with floor 2000, trims that batch until the broader support-adjusted share-price scalar times batch no longer exceeds the 55000 gate, recomputes the pressured support-adjusted share-price scalar and the paired price/book ratio, then tests the remaining gates in a fixed order: share-price floor 22, proceeds floor 55000, current cash from 0x2329/0x0d against the chosen highest-coupon bond principal plus 5000, one later stock-issue cooldown gate that converts the current issue mixed-radix calendar tuple at [company+0x16b/+0x16f] through calendar_point_pack_tuple_to_absolute_counter 0x0051d3c0 and compares the result against the active world absolute calendar counter [world+0x15], and only then the coupon-versus-price-to-book approval ladder 0.07/1.3 -> 0.14/0.35. The issue mutator preserves the previous tuple in [company+0x173/+0x177] and refreshes the current tuple from [world+0x0d/+0x11] on the derived-pricing lane. On success it issues two same-sized tranches through repeated company_issue_public_shares_and_raise_capital calls and publishes a separate equity-offering news family rooted at localized id 4053, not the earlier debt or buyback headline family. The dividend side is bounded too: it requires the dividend toggle [0x006cec78+0x4a93] to be clear, mode 0x0c, at least 1 year since [company+0x0d2d], and at least 2 years since founding, then averages the last three years of the net-profits lane 0x2b, folds in the unassigned-share pool and the current 0x0d band, applies the map-editor building-growth setting [0x006cec78+0x4c7c], treats growth setting 1 as a 0.66 scale-down and setting 2 as a zeroing pass on the current dividend, quantizes surviving adjustments in tenths, and finally clamps against company_compute_board_approved_dividend_rate_ceiling 0x00426260. The linked-transit route-seeding side has one tighter sibling now too: company_reset_linked_transit_caches_and_reseed_empty_train_routes 0x00401940. It clears the two company-side linked-transit cache timestamps, forces one immediate cache rebuild through 0x00409720, strips route lists from company-owned trains in modes 0x0a/0x13, and then re-enters train_try_append_linked_transit_autoroute_entry 0x00409770 only when a train's route list has become empty. On the wider chooser question, the current evidence is also tighter than before: every recovered external owner of 0x00402cb0 is still in the city-connection family, so the two later direct placement lanes currently read as city-connection fallback behavior rather than a broadly shared world placement service. It can still unwind through route-state cleanup without committing new placed structures, so the exact lower helper semantics are not fully closed, but the broader chooser is no longer anonymous and its main policy split is now visible. The two lower helpers directly under those commit lanes are bounded now too: placed_structure_project_candidate_grid_extent_offset_by_rotation 0x00417840 is the shared projected-footprint offset helper over candidate bytes [candidate+0xb8] and [candidate+0xb9], and placed_structure_validate_projected_candidate_placement 0x004197e0 is the shared go-or-no-go validator that checks company, territory, world-tile, and footprint occupancy state before either direct-placement commit is allowed to fire. Its strongest current subtype branch is a station-attachment or upgrade-style lane keyed by [candidate+0x32] == 1, which now has the concrete failure family 2901..2906: blocked upgrade footprint, ground not flat enough, not your track, insufficient track-laying capacity, cannot connect to existing track, and ground too steep. That tightens the chooser materially without yet proving that the validator is station-only for every caller. The recurring outer owner is tighter now too: placed_structure_collection_refresh_quarter_subset_route_style_state 0x00413580 walks every fourth live placed structure from a scenario-time-derived offset and re-enters the per-site rebuild with stack flag 0, giving the route-style lane a concrete recurring maintenance sweep under simulation_service_periodic_boundary_work rather than only a floating caller note. One neighboring helper is now bounded on the message side too: shell_building_detail_handle_subject_value_row_band_action 0x004ba270 switches over the clicked row family 0x7d07..0x7d14, treats subject bytes +0x21/+0x22/+0x23 as one current selection plus one bounded low/high pair, increments the family dirty latch at 0x006cfe0c on change, and republishes the refreshed value through the shared shell control helper on code 0x66. One neighboring helper is now bounded on the side-list path too: shell_building_detail_propagate_selected_subject_state_into_side_list 0x004b9ec0 walks the sibling list owner at 0x006cfe08, copies the active subject state into each side-list record, mirrors the current service or capability id at +0x24, and preserves the 0x40/0x20/0x10 subflags from the active subject. That means the value-row actions and later selector rows now read as propagating one shared building-detail state across the sibling list rather than only mutating one isolated subject record. One neighboring helper is now bounded separately too: shell_building_detail_refresh_subject_pair_value_rows 0x004bad20 owns the mutually exclusive value-row pairs 0x7d07/0x7d08, 0x7d11/0x7d12, and 0x7d13/0x7d14, choosing among them from the same selected-subject flag byte and payload fields at +0x22/+0x23, while the larger cargo-or-service row owner also gates the extra visual lanes 0x7d6a, 0x7d6b, and 0x7d9d from that same subflag family. The asset-string block is tighter too: that branch family now explicitly uses AnyCargo.imb, AnyFreight.imb, PassMail.imb, Caboose.imb, and Dining.imb, with the bit-0x20 special lane already aligned to Caboose.imb and the sibling bit-0x10 special lane now aligned to Dining.imb. The larger 0x7f58..0x801f band is no longer just a styled row family either: shell_building_detail_present_flagged_service_capability_popup 0x004b9fd0 is now grounded as its explanatory popup callback. It resolves either one fixed express-side row from 0x00621e04 or one active candidate or service id from [subject+0x24], then formats one popup through the shell message-box path. The neighboring refresh helper shell_building_detail_refresh_flagged_service_capability_rows 0x004b9a20 is tighter now too: 0x7d07..0x7d1c is not one anonymous block, but a real mask partition over subject bits 0x20 and 0x10, with one zero-mask pair, one bit-0x20-only pair, one exclusive-or pair, and later one-bit and two-bit indicator rows. RT3.lng now closes the fixed popup text family too: the single-line branch uses 3922 %1\nLoads available at %2: %3, while the richer ordinary-candidate branch uses 2981 %1\nLoads available at %2: %3 Current Price: %4 and can append 2982 Price at next station, %1: %2 (%3%4). The selector band is narrower too: current refresh-side evidence shows 0x7f58..0x801f as one selected-ordinal highlight family over the three fixed express rows plus the ordinary active-candidate rows, not as a generic unstructured list. The neighboring 0x8020..0x8051 band is tighter too: it is primarily the matching remove-entry family for the selected subject's live id list, with two special row indices re-routing into the 0x7d0f/0x7d10 subflag-clearing path instead of ordinary list compaction when the current 0x20/0x10 service-bit combination demands it. That means the exact captions are no longer broadly open across the whole selector family: the fixed express-side rows, the mask partitions, and the add/remove structure are grounded, and the remaining caption gap is mostly the ordinary candidate rows further down the same band. The top-level toggles are tighter now too: the paired 0x7d02/0x7d03 controls are the real mode switch over subject bit 0x40, choosing between the bounded pair-value branch and the current-selection/status branch around 0x7d0d/0x7d0e, while the smaller 0x7d0f/0x7d10 controls flip the same special-service subflags later rendered as Caboose and Dining Car. One adjacent control is tighter now too: the extracted BuildingDetail.win resource contains the plain-English line Set the initial cargo amount for 'Disable Cargo Economy' scenarios., and the 0x7d01 plus 0x7d09/0x7d0a message-side branch can mirror the current subject or selection through shell_building_detail_submit_aux_owner_subject_sync_request 0x004b9e10 into the auxiliary owner queue at [0x006cd8d8+0x8f48], with side-owner presence now explicitly grounded through shell_has_auxiliary_preview_owner 0x00434050. That queued request is tighter too: both current callsites forward the same side-list mirror latch at [0x006cfe08+0x0c], so the auxiliary owner now clearly sees not just the staged subject but also whether the local BuildingDetail side-list is in mirrored-subject mode. The same 0x7d01 lane also now has one clear rejection note: localized id 3587 This option is only available by following the tutorial. now sits behind the active tutorial flag at 0x006d3b4c and the cached previous tutorial expected-control id at 0x00622b38, while the neighboring tutorial helper tutorial_advance_step_and_refresh_expected_control_ids 0x00516be0 now grounds 0x00622b34/0x00622b38/0x00622b3c as the current and previous expected-control cache rather than anonymous globals. The last field is tighter now too: 0x00622b3c is currently best read as the active tutorial step's alternate-accepted companion control id, because the generic shell control path compares clicked control ids against it directly and suppresses the 3587 tutorial rejection when they match. That does not fully close the player-facing caption bind for every control, but it does bound the neighboring side-owner sync and tutorial-rejection lane instead of leaving it as anonymous glue. The extra pre-insert gate is narrower than it first looked. It is now grounded as tutorial-only: tutorial_validate_train_route_station_indicator_step 0x00516d00 checks the current tutorial step from the shell tutorial descriptor table at 0x00622b48 before a live station-or-transit site id can be committed into the staged route entry, and the currently accepted steps align with localized prompts 3777 and 3778, the two train-routing tutorial instructions that tell the player to click the Milan and Turin station indicators. Outside that tutorial state family, the route-entry insertion path is not gated there. The adjacent validator is tighter now too: train_route_list_validate_reachability_and_station_pair 0x004b2c10 walks that same route list, resolves placed-structure-backed entries through the live placed-structure and route-node collections, uses the direct route-node payload branch for the remaining entry family, and fails with 3089..3091 when the resulting route cannot be traversed or does not preserve a valid terminal station pair. The post-validation follow-on is bounded too: train_current_route_context_uses_strict_reachability_mode 0x004a9460 is now the small shared gate above the stricter branch, keyed off the current linked route object's downstream class type, and train_set_route_operating_mode_and_scalar 0x004ab980 now reads as the shared train mode setter beneath route editing, with the local and multiplayer insertion paths choosing mode 0x13 only when that stricter second validation succeeds and mode 0x0a on the looser fallback path. The first deeper world-mode interaction branch is now better bounded: GameUppermost.win hotspots, cursor drag, held Shift state, discrete shell view-step commands, direct keyboard turn/pan/zoom bindings, the TrackLay.win and StationPlace.win world-command surfaces, and a frame-owned hover or focus-target transition branch all feed the same shell-controller-backed path. The remaining uncertainty has moved farther from basic ownership: the hover-target branch clearly exists, and 0x07d6 now looks like the shared main-world interaction surface rather than a generic detail button for one tool family only. One more shell-side consumer is bounded now too: 0x004bc350 is a world-surface brush handler over that same 0x07d6 control plus the adjacent mode family 0x0faa..0x0faf and ordinal strip 0x0fa0..0x0fa7. That family is no longer just a generic unlabeled brush owner: the detail-panel manager now grounds the sibling tool-window strip immediately above it as Bulldoze.win, ChangeHeight.win, ChangeTrees.win, PaintTerrain.win, PaintRegion.win, PaintSound.win, and PaintTerritory.win, each with its own constructor, refresh pass, and message owner beneath the same controller rooted at 0x006d0818. Once its local drag latch is active it dispatches the current mode dword at [0x006d0818+0x8c] into the companion-float helpers 0x0044d4e0, 0x0044d880, and 0x0044da70, or into the secondary-raster nibble path 0x00448e20 -> 0x00419110, so the remaining uncertainty has narrowed from ownership to the exact one-to-one mode-button mapping inside that grounded tool-window strip. The PaintTerrain.win side is tighter now too: constructor 0x004f7ce0 seeds shell singleton 0x006d1304, callback root 0x006d1334, a constructor-time bulk-update latch at 0x006d1330/0x006d1331, and the broader terrain mode or scalar state from 0x00622748..0x00622788 plus 0x006d1308..0x006d1324; it then registers the callback strip 0x004f5960, 0x004f59f0, 0x004f6070, and 0x004f69e0 through 0x00540120. The direct message owner under that same family is no longer just a loose branch fan-out either: 0x004f6f50 owns messages 2/0xca/0xcb, keeps control 0x07d6 as the live world-surface drag latch, routes explicit undo control 0x2775 into 0x004f5c30, maps the selector and mode strips 0x2711..0x2730, 0x27d9..0x27df, 0x283d..0x2843, 0x28a1..0x28e6, 0x2915..0x291e, 0x2964..0x2967, and 0x29cd.. into the cached terrain lanes, and then fans the active drag path into preview helpers 0x004f6930, 0x004fb5e0, 0x004fc280, 0x004fc4d0, and 0x004fc630 depending on the current terrain mode. Inside that same family 0x004f5a80/0x004f5c30 are now the bounded local undo snapshot pair, 0x004f5dd0 is the tiny active-scalar-group selector, 0x004f6b50 owns the ten-entry mode strip rooted at 0x28dd, 0x004f6390 is the broad mode-panel repaint owner, 0x004f6250 is the mode-dependent world-dispatch bridge, 0x004f6930 samples the current preview raster at world coordinates, and 0x004fb5e0 is the heavier preview-raster rebuild and shell-surface publish worker. The next local helpers under that same family are tighter now too: 0x004f5ea0 and 0x004f5ec0 are just the two tiny special-mode predicates (mode 5, variant 2) and (mode 4, variant 2), 0x004f8770 is the weighted RGB sampler over the current preview or undo-backed raster neighborhood, 0x004f89b0 is the local byte-grid connected-component grower over the eight-neighbor tables 0x00624b28/0x00624b48, and 0x004f8bb0 is the main drag-path preview compositor that consumes the drag sample strip [this+0xf0/+0xf4/+0xf8], allocates temporary float or byte grids, and then rasterizes the surviving preview rectangle through the current terrain descriptor tables at 0x005f3500, the weighted color sampler 0x004f8770, the component grower 0x004f89b0, and several live world samplers before writing final RGBA pixels back into the preview surface. The late tail under that same compositor is tighter too: the mode-4, variant-2 path toggles secondary-raster byte-2 bit 0x20 by comparing current and previous cells through 0x00534f40; the broader mode-4/5 world-facing branch samples class set 2/4/5 through 0x00534ec0, re-enters 0x0044de30 and 0x0044df10, latches pending world coordinates into [0x006d1304+0x78/+0x7c], and rewrites the low nibble plus the signed overlay-vector planes through 0x00448df0, 0x00448e20, 0x00448ec0, 0x00448ee0, 0x00448e60, and 0x00448e90. After the optional mode-5 smoothing sweep through 0x004f8370, the publish tail either materializes one shell preview surface through 0x0051f090 -> 0x00534730 or, for the mode-4/5 world-facing variants, converts the surviving preview rectangle back into world-space bounds and re-enters 0x0044e940, 0x00452f20, and 0x0044d410. The companion preview-rebuild owner 0x004fb5e0 is tighter on entry, too: 0x004f726c is the early rebuild path that first copies the live preview raster into [this+0x118] and snapshots undo state through 0x004f5a80, while 0x004f7ada is the later drag-active path that first allocates a temporary occupancy mask before rebuilding and then conditionally mirrors that mask through 0x00450520 on the world-mode-0x17 side path. So the remaining uncertainty has narrowed again from family ownership to the exact meaning of a few per-mode scalar and token lanes, not to whether PaintTerrain.win itself is still a mixed shell/world owner. The same brush strip is tighter now too: 0x004bc210 stores the selected ordinal and refreshes one scalar caption from table 0x00621e24, 0x004bc260 exposes the cached world coordinate pair plus the currently selected scalar, and 0x004bc290 restyles the ordinal strip 0x0fa1..0x0fa7 plus the mapped mode strip 0x0faa..0x0faf against the current mode dword [0x006d0818+0x8c]. The next unresolved layer is narrower and more semantic: the setup side now has one grounded owner, world_run_post_load_generation_pipeline, and its building-side branch is no longer just one opaque block. We now have a region family, a region-border overlay rebuild, a region-owned structure-demand and placement dispatcher, and a deeper per-region worker that computes category demand, subtracts existing coverage, and tries candidate placements. The category map is tighter too: category 0 falls back to House, category 2 is the year-gated weighted region-profile family that also feeds the localized Industry Weightings stats panel, and category 3 now reaches a separate pool-driven picker whose fallback label is Commercial but whose aligned player-facing stats bucket is City Support. The normalized region band is tighter too: world_region_normalize_cached_structure_balance_scalars 0x00422320 no longer just writes an anonymous cached preview band at [region+0x2e2/+0x2e6/+0x2ea/+0x2ee]. Current growth-report evidence now grounds [region+0x2e2] as the weighted-profit-margin scalar and [region+0x2ee] as the annual-density-adjust scalar later formatted as a percent in Stats - City/Region, with [region+0x2e6/+0x2ea] left as the intermediate normalized-delta and clamped companion slots beneath that final adjust term. The per-region prepass feeding that normalization is tighter too: 0x00420d40 clears [region+0x306/+0x30a/+0x30e], walks the linked placed-structure chain from [region+0x383], accumulates two local placed-structure metrics through 0x0040ca70 and 0x0040ca80, and only for class-0 candidates also folds source field [source+0x141] through 0x0040cec0 into the third accumulator before tailing into the later scalar refresh. That tail helper 0x00420560 is tighter now too: on class-0 regions it revisits the same linked chain and folds a class-mix contribution into [region+0x312], with one source-derived term for candidate class 0, a separate branch keyed by [candidate+0x78c] and [site+0x246] for class 2, one fixed increment for class 3, and no current contribution from class 1. The remaining setup-side uncertainty has therefore narrowed again: the region seed and border-overlay pair clearly complete before the Setting up Players and Companies... banner is posted; [0x006cec74+0x174] now looks like the direct building-population gate; [0x006cec74+0x178] now looks like the direct seeding-burst gate and selected-year-adjust policy; and [0x006cec74+0x68] now aligns with editor-map mode because the same flag forces the .gmp family in the shell file coordinators while suppressing the later building and seeding branches and diverting the deeper region worker into alternate logic. One write side for that [shell+0x178] policy is now grounded too: inside shell_dispatch_ui_command 0x00464410, command ids 0x9d26..0x9d28 store command_id - 0x9d26 directly into [0x006cec74+0x178], yielding live values 0, 1, and 2. That means the later restore branch is no longer gated by an abstract hidden shell latch; at least one of its adjustment inputs is an explicit UI launch policy and current evidence still does not show that value being recovered from saved state. The 319 lane itself is no longer the open structural gap; it now clearly owns chairman-profile slot seeding, profile-record materialization, a shell editor surface over the same local record family, and a separate live-company presentation path through the company-list window. The later interior order of that same 319 lane is tighter now too: after the route-entry collection refresh on 0x006cfca8 it refreshes the auxiliary route-entry tracker collection 0x006cfcb4, then runs placed_structure_collection_refresh_local_runtime_records_and_position_scalars 0x004133b0, then a flagged world-grid cleanup sweep through the compact grid-flag query 0x00448af0 plus the neighboring local chunk-cell write helper 0x00533fe0, and only after that the later route-entry post-pass at 0x00491c20. The same 319 lane is tighter internally now too: before that later world and shell reactivation tail, world_entry_transition_and_runtime_bringup runs one distinct post-bundle status and runtime refresh phase that posts progress ids 0x196 and 0x197 through 0x005193f0/0x00540120 with paired 0x004834e0 follow-ons, refreshes the live event collection at 0x0062be18 through scenario_event_collection_refresh_runtime_records_from_packed_state 0x00433130, rebuilds the scenario-side port-or-warehouse cargo recipe runtime tables through 0x00435630, and then runs the named-candidate availability preseed through 0x00437743. One later subphase is tighter now too: before the broad world-reactivation sweep it posts progress ids 0x32dc/0x3714/0x3715, reloads one 0x108-byte packed profile block through 0x00531150, conditionally copies staged runtime-profile bytes back into 0x006cec7c while latch [profile+0x97] is set, mirrors the grounded campaign-scenario bit [profile+0xc5] and sandbox bit [profile+0x82] into world bytes [world+0x66de] and [world+0x66f2], and restores the selected year/profile lane through a tighter two-stage calendar path than before. Current local disassembly now shows the raw saved lane at [profile+0x77] first feeding helper 0x0051d3f0 with constant components (month=1, day=1, subphase=0, tick=0), which writes the resulting Jan-1-style tuple dwords into [world+0x05/+0x09]. Only after that seed does the same lane enter one mode-sensitive adjustment branch: non-editor startup mode can decrement the lane by 1 or 3 depending on shell-state editor gate [0x006cec74+0x68], shell-side selected-year-adjust policy [0x006cec74+0x178], and the saved special-condition slot [0x006cec78+0x4af7], and only that adjusted lane then feeds helper 0x0051d390 before world_set_selected_year_and_refresh_calendar_presentation_state 0x00409e80 stores the final absolute counter into [world+0x15] and refreshes [world+0x0d/+0x11]. That means the restore no longer reads as a direct [profile+0x77] -> [world+0x15] copy; the raw lane seeds the tuple immediately, but the final absolute-counter restore still depends on live shell/startup context. That dependency is tighter now too: current local evidence shows [shell+0x178] == 1 decrementing the restored lane by 1, [shell+0x178] == 2 subtracting 3, and otherwise a nonzero [0x006cec78+0x4af7] supplying the fallback -1 branch. That field is no longer unresolved: current local disassembly now shows 0x00436d10 bulk-zeroing the dword table rooted at [startup+0x4a7f] through rep stos, which includes +0x4af7, while the editor-side special conditions owner at 0x004cb2b0/0x004cb8e0 counts and commits that same 49-entry table from the static rule descriptors at 0x005f3ab0. The .smp save or restore family now grounds that live band directly too: world_runtime_serialize_smp_bundle 0x00446240 writes 49 dwords from [world+0x4a7f..+0x4b3f] plus one trailing scalar at [world+0x4b43], and world_load_saved_runtime_state_bundle 0x00446d40 restores the same fixed 0xc8-byte band symmetrically. Slot 30 in that table is localized pair 3722/3723 Disable Cargo Economy, so +0x4af7 now reads as the live copy of that saved scenario rule, not a startup-runtime-only mystery latch. The neighboring fixed reads line up with the same rule cluster too: +0x4aef is slot 28 Completely Disable Money-Related Things, +0x4af3 is slot 29 Use Bio-Accelerator Cars, +0x4afb is slot 31 Use Wartime Cargos, +0x4aff is slot 32 Disable Train Crashes, +0x4b03 is slot 33 Disable Train Crashes AND Breakdowns, and +0x4b07 is slot 34 AI Ignore Territories At Startup. So the remaining loader gap is narrower than before: the restore still depends on live shell policy [shell+0x178], but the +0x4af7 input itself is save-derived scenario rule data rather than something that requires runtime tracing to discover. Its read-side family is no longer isolated to the selected-year restore either: it also shapes the chunk size in simulation_run_chunked_fast_forward_burst 0x00437b20 and appears in candidate/local-service selection and station-detail-side scoring branches around 0x0047f910, 0x00410d87, and 0x005069c6, which now makes this whole slot cluster look like broader runtime consumers of scenario special conditions rather than one startup-only mode enum. One file-side anchor is now tighter too: the checked classic and 1.05 gmp/gms/gmx corpus does expose the same aligned 0x0d64..0x0e2c 50-dword band as the grounded .smp runtime save or restore copy into [world+0x4a7f..+0x4b43], but most checked file families only populate a sparse subset of that band. The first 36 dwords still behave like the older inferred fixed rule matrix with hidden slot 35 fixed to sentinel value 1, while the trailing 13 unlabeled rule lanes plus one scalar vary much more selectively by file family. Current local corpus scans make that split concrete: the grounded 1.05 scenario-save family (p.gms, q.gms) stably lights lanes 35, 37, 39, 44, 45, 46, 47, 48; the base 1.05 save family (Autosave.gms, nom.gms) only shares lane 35 stably and otherwise varies sparsely through 42, 45, and 47; the checked grounded 1.05 maps, the lone 1.05 alt save, and the visible sandbox-family .gmx files keep only the sentinel lane 35 nonzero. So the current loader boundary is narrower than before: the .smp path still gives a grounded direct runtime-band restore, and checked gmp/gms/gmx files now show a partially populated projection of that same aligned band rather than a wholly separate fixed record family. The overlap against the later scalar window is now explicit too: trailing band indices 36..49 are byte-identical with post-window offsets 0x00..0x34, so every nonzero lane in that prefix of the post-sentinel scalar window is also a nonzero lane in the aligned runtime-rule band. That means the real “other fields” boundary inside the post-sentinel window starts only at 0x0e2c: 0x0df4..0x0e2c is the aligned-band overlap prefix, while 0x0e2c..0x0f30 is the later tail that still looks like save-side scalar state. Local corpus scans now make that tail split more specific. The base 1.05 save family (Autosave.gms, nom.gms) shares a stable tail subset at relative offsets 0xb4, 0xc0, 0xe0, 0xfc, and 0x100, with additional per-file lanes around them. The 1.05 scenario-save family (p.gms, q.gms) has a much denser stable tail covering 0x08, 0x0c, 0x10, 0x14, 0x20, 0x24, 0x28, 0x30, 0x34, 0x3c, 0x5c, 0x6c, 0xa0, 0xa8, 0xbc, 0xc0, 0xc4, 0xc8, 0xcc, 0xdc, 0xe0, 0xe4, 0xe8, 0xf4, 0xf8, and 0xfc; those values still differ per save, but the occupancy is stable. The lone 1.05 alt save (g.gms) only lights 0x20, 0x34, 0xf0, and 0xf4. Grounded map families and classic saves keep the tail zeroed, while the only current map-side outlier remains Tutorial_2.gmp under the broad unknown map-family bucket. The immediately following fixed file window at 0x0df4..0x0f30 is now bounded separately as well: checked maps and classic saves leave that whole post-sentinel band zeroed, while checked 1.05 saves carry sparse nonzero dwords there, many of which decode cleanly as normal little-endian f32 values. That makes the adjacent band look like a 1.05 save-only runtime band rather than scenario-static payload, even though its semantics are still open. One numeric alignment inside that band is now exact too: the tail start 0x0e2c is the same relative distance from the aligned runtime-rule base 0x0d64 as live object offset +0x4b47 is from grounded world-rule base [world+0x4a7f], so the bounded tail window 0x0e2c..0x0f30 is offset-aligned with live bytes [world+0x4b47..+0x4c4b]. The first grounded live field at that boundary is no longer anonymous. 0x004367c0 sets one outcome mode in [world+0x4a73], zeros [world+0x4d], snapshots the selected-year lane to [world+0x4c88], and then copies localized id 2923 You lose. or 2924 You win, cheater... into [world+0x4b47]; 0x00472dd0 formats localized id 3918 %1 has won the game! with one live profile name and writes that string into the same destination; and one compact runtime-effect branch inside world_apply_compact_runtime_effect_record_to_resolved_targets 0x00431b20 resets the same destination to the fixed placeholder token at 0x005c87a8. That gives a grounded live interpretation for the start of the tail: [world+0x4b47] is the start of a victory or outcome status-text buffer, not a float lane. The same evidence also gives a useful caution: those live helpers copy up to 0x12c bytes into [world+0x4b47..+0x4c73], so the current bounded file-tail window 0x0e2c..0x0f30 cuts through the first 0x104 bytes of a grounded text field rather than ending on a clean live-field boundary. One small continuation probe now tightens that edge: the remaining file window 0x0f30..0x0f58 is exactly the last 0x28 bytes needed to reach the clean live-field boundary at [world+0x4c73], and checked 1.05 saves still carry sparse nonzero bytes in that continuation window rather than a trailing text-looking suffix. Checked 1.05 save bytes in the aligned region therefore still do not resemble preserved text; they stay mostly zero at the beginning and many nonzero lanes decode as ordinary f32 values. So the safest current note is: the tail is offset-aligned with the live object beyond +0x4b43, but it is not yet a validated byte-for-byte mirror of the live [world+0x4b47] status-text buffer, and the current nonzero save-side content continues right up to the first clean field edge at 0x0f58. The next exact grounded fields after that edge are byte lanes, not restored dwords: 0x0f59 maps to [world+0x4c74] Auto-Show Grade During Track Lay, 0x0f5d maps to [world+0x4c78] Starting Building Density Level, 0x0f61 maps to [world+0x4c7c] Building Density Growth, 0x0f65 maps to grounded dword [world+0x4c80] leftover simulation time accumulator, and 0x0f6d maps to byte [world+0x4c88] selected-year lane snapshot. The first later grounded dword after that is [world+0x4c8c] at 0x0f71. That means the simple 4-byte file-lane model stops matching grounded live field boundaries immediately after the text-buffer edge: the post- 0x0f58 file bytes are still offset-correlated to live state, but they are no longer naturally dword-aligned with the next grounded object fields. The new byte-neighborhood probe makes the mismatch more concrete. In checked 1.05 scenario saves, the exact grounded byte offsets themselves do not look like clean selector values: p.gms carries 0x33 at 0x0f5d and 0x8c at 0x0f6d, while q.gms carries 0xcc and 0xba at those same offsets. The only clean float-looking starts in that neighborhood instead appear one byte earlier, at 0x0f5c and 0x0f6c: p.gms decodes those as roughly 7.6 and 6.0172, while q.gms decodes them as roughly 23.6 and 44.6824. That tightens the current read further: the checked save bytes remain offset-correlated to the live [world+0x4c74..+0x4c8c] neighborhood, but they are still not a validated byte-for-byte mirror of the exact live field layout. Local A second byte-oriented neighborhood immediately after that now has the same kind of split rather than a clean restored-field mirror. The earlier grounded anchors in that band all stay zero in the checked 1.05 saves: exact file offset 0x0f87 maps to selected-year bucket companion scalar [world+0x4ca2], while 0x0f93 and 0x0f97 map to the two startup-dispatch reset-owned bands [world+0x4cae] and [world+0x4cb2], and the local corpus leaves all three exact dword starts zeroed. The same is true for the later exact byte-owned policy lanes: file offsets 0x0f78, 0x0f7c, 0x0f7d, and 0x0f7e map cleanly to grounded byte fields [world+0x4c93] and [world+0x4c97..+0x4c99]: the linked-site removal follow-on gate plus the three editor locomotives-page policy bytes All Steam Locos Avail., All Diesel Locos Avail., and All Electric Locos Avail.. In the checked 1.05 save corpus those four exact byte lanes all stay 0, which is at least structurally clean. The later grounded dword fields in the same neighborhood are less direct again. Exact file offset 0x0f9f maps to [world+0x4cba] (the station-list selected-station mirror) and exact offset 0x0fa3 maps to cached available-locomotive rating [world+0x4cbe], but the checked save bytes at those exact dword starts do not look like clean preserved ids or floats. The only stable float-looking starts sit three bytes earlier, at 0x0f9c and 0x0fa0: p.gms yields roughly 96.8754 and 186.4795, q.gms yields 329.9467 and the same 0x0fa0-side candidate shape, g.gms yields 7.0 and 95.8507, and Autosave.gms only shows the later 0x0fa0 candidate at about 68.2629. So this later band now has the same conservative read as the post-text one: the save bytes are still offset-correlated to grounded live fields, but the exact live byte or dword layout is not yet validated as a direct on-disk mirror. One more structural cut is now grounded beyond that neighborhood. The aligned scalar plateau 0x0fa7..0x0fe7 ends exactly at the later recipe-book root [world+0x0fe7] already grounded in the port-or-warehouse cargo editor and runtime rebuild path. We still do not have live semantic names for the plateau itself, but its aligned dword run now splits cleanly by save family. The base 1.05 saves (Autosave.gms, nom.gms) carry one stable signature with 0x0faf = 0x8000003f, 0x0fb3 = 0x75c28f3f, repeated 0x75c28f3c lanes through 0x0fbf, a sign-flipped lane 0x0fc3 = 0xa3d70a3c, one tiny marker at 0x0fc7 = 0x0000003b, and 0x0fcb = 0x00300000. The scenario-save family (p.gms, q.gms) carries a different stable plateau over the same offsets, beginning 0x0faf = 0x4000003f, 0x0fb3 = 0xe560423f, then 0x03126f3b, 0x1374bc3c, and paired 0x23d70a3c lanes at 0x0fbf/0x0fc3, with 0x0fc7 = 0x0000003c. The alt-save family (g.gms) follows the base signature through 0x0fc7, then diverges sharply into the same 0xcdcdcd.. fill pattern already seen in its earlier header lanes. So the current best fit for 0x0fa7..0x0fe7 is a family-shaped aligned scalar plateau that belongs to save-side runtime state and terminates immediately before the grounded recipe-book block, not one more directly named live-field mirror. One conservative loader-side summary probe now starts exactly at that recipe root instead of extending the plateau model further. The fixed recipe-book block spans twelve books from 0x0fe7 with stride 0x4e1, and the checked map/save pairs Alternate USA.gmp -> Autosave.gms, Southern Pacific.gmp -> p.gms, and Spanish Mainline.gmp -> g.gms preserve that rooted block byte-for-byte in the sampled local corpus. The current probe therefore treats it as preserved scenario payload rather than save-only runtime drift and only reports per-book signatures: a coarse head kind over the pre-line region, the raw book+0x3ed annual-production dword, and one raw summary for each of the five fixed 0x30-byte cargo lines beginning at book+0x3f1: coarse line kind, raw mode dword, raw annual-amount dword, and the raw supplied/demanded cargo-token dwords at +0x08 and +0x1c. That is enough to separate zero, 0xcd-filled, and mixed books or lines without overstating line semantics beyond the grounded editor/runtime ownership already documented below. Local corpus clustering now makes the remaining split more specific. The base 1.05 save family (Autosave.gms, nom.gms) shares a narrow tail-heavy subset with stable relative offsets 0xec, 0xf8, 0x118, 0x134, and 0x138, while still varying in value across files. The 1.05 scenario-save family (p.gms, q.gms) shares a much broader stable set spanning almost the whole window from 0x04 through 0x134, again with per-file scalar differences but consistent occupancy. Pairwise compare runs tighten that read further: Autosave.gms vs nom.gms does not preserve one common numeric tail signature even at the shared base-save offsets, and p.gms vs q.gms keeps the broad scenario-save occupancy pattern but still changes every shared value, with q.gms additionally lighting two extra lanes at 0x78 and 0x84. So the current best fit is “family-shaped live scalar state” rather than family-default constants. The lone 1.05 alt-save sample (g.gms) only lights up four lanes at 0x58, 0x6c, 0x128, and 0x12c. The checked 1.05 maps and classic saves stay zero in that same bounded window, which strengthens the current read that this is runtime-save scalar state rather than generic map payload. One older unknown map-family outlier in the local corpus does still carry a populated window: Tutorial_2.gmp under the classic install tree. So the safest current note is “zero for grounded map families and classic save families, nonzero for observed 1.05 save families, with one older unknown-map exception.” Static consumer grounding is still sparse for that tail: direct object-offset hits currently only name the trailing scalar [world+0x4b43] through the editor panel and .smp save or restore family, while local opcode searches do not yet surface equally direct reads for the intervening +0x4b0b..+0x4b3f tail lanes. So the save-file family clustering is now strong, but those later tail scalars remain structurally bounded rather than semantically named. The same branch is no longer world-entry-only either: current local disassembly now shows the identical lane-adjust and 0x51d3f0 -> 0x51d390 -> 0x409e80 sequence in the post-fast-forward selected-year tail at 0x004370e0, which lines up with the existing post-fast-forward callers already mapped under 0x00433bd0, 0x00435603, 0x0041e970, and 0x00436af0. That restore now also has some neighboring slot semantics bounded well enough to carry in the loader notes. Slot 31 [0x006cec78+0x4afb] is no longer best read as an unnamed runtime cargo-economy latch: local disassembly now ties it directly to the saved special-condition table entry Use Wartime Cargos, and the strongest current runtime owner is structure_candidate_collection_refresh_cargo_economy_filter_flags 0x0041eac0. Inside that candidate-collection sweep the branch at 0x0041ed37 only activates when slot 31 is set and then treats the string family Clothing, Cheese, Meat, Ammunition, Weapons, and Diesel as one special cargo set before writing the live candidate filter byte [entry+0x56]. That makes the old read-side note around 0x00412560 tighter too: the neighboring descriptor gate is now best understood as using the live copy of the Use Wartime Cargos scenario rule, not an anonymous cargo-economy mode byte. Slot 34 [0x006cec78+0x4b07] is similarly bounded on the runtime side: the wrapper at 0x004013f0, which sits immediately above the broader company-start or city-connection chooser 0x00404ce0, snapshots region dword [entry+0x2d] across all 0x18 live region records in 0x006cfc9c, zeros that field while the chooser runs, and then restores the original values on exit. That is a strong current fit for the editor rule AI Ignore Territories At Startup, even though the exact meaning of region field +0x2d remains open. Slot 29 [0x006cec78+0x4af3] is less semantically tidy but still worth carrying as a bounded consumer family: the branch at 0x0041d286 activates one later placed-structure or building-side scoring path only when that slot is nonzero and the linked candidate or era record at [entry+0x41] equals 5, while two already-grounded world helpers world_scan_secondary_grid_marked_cell_bounds 0x0044ce60 and world_service_secondary_grid_marked_cell_overlay_cache 0x0044c670 also gate on the same slot. So the identity of slot 29 as saved rule data is grounded, but the downstream runtime semantics are still mixed enough that the loader should preserve the raw value without trying to rename its whole consumer family yet. The neighboring train-safety slots are now bounded enough to keep as a cautious runtime split too. Slot 33 [0x006cec78+0x4b03] Disable Train Crashes AND Breakdowns is the coarse gate in the currently recovered train-side deterioration family around 0x004af8a0: the very first branch at 0x004af8ab jumps straight to the function tail when the slot is set, bypassing the year-scaled threshold build, the later random or threshold comparison, and the two follow-on state transitions at 0x004ad7a0 and 0x004ada00. Slot 32 [0x006cec78+0x4aff] Disable Train Crashes is narrower in the same family: after the threshold path has already run, the branch at 0x004af9c1 uses slot 32 to suppress only the lower failure-transition path and force the milder follow-on at 0x004ada00. That same slot-33 read also appears in the smaller train-side scalar query at 0x004ac460, where setting it returns one fixed float immediately before the ordinary route-object-dependent calculation runs. So the current best loader-facing read is: slot 33 is the broad train deterioration bypass, slot 32 is the narrower crash-only branch inside that same family, but the exact player-facing names of the two unnamed train helpers still need one more naming pass. That restore now also has one concrete file-side correlation in the classic .gms family: local save inspection now consistently finds 0x32dc at 0x76e8, 0x3714 at 0x76ec, and 0x3715 at 0x77f8 in Autosave.gms, kk.gms, and hh.gms, leaving one exact 0x108-byte span from 0x76f0 to 0x77f8 between 0x3714 and 0x3715. That span already carries staged-profile-looking payload text such as British Isles.gmp, so the current static-file evidence now supports the atlas-side 0x108 packed-profile note for the classic save family even though the exact field layout inside that block is still unresolved. The same classic corpus is tighter now too: inside that 0x108 span the map-path C string begins at relative offset 0x13, the display-name C string begins at 0x46, the block is otherwise almost entirely zeroed, and the three local samples are byte-identical except for the leading dword at +0x00 (3 in Autosave.gms and hh.gms, 5 in kk.gms). The currently atlas-tracked bytes [profile+0x77], [profile+0x82], [profile+0x97], and [profile+0xc5] are all 0 in that classic sample set, so the current file-side evidence grounds the block boundaries and the embedded strings but does not yet show live examples of those branch-driving latches being set. One 1.05-era file-side analogue is now visible too, but only as an inference from repeated save structure rather than a disassembly-side field map: local .gms files in rt3_105/Saved Games carry one compact string-bearing block at 0x73c0 with the same broad shape as the classic profile slab, including a leading dword at +0x00, one map-path string at +0x10, one display-name string at +0x43, and a small nonzero tail around +0x76..+0x88. In that 1.05 corpus the analogue bytes at relative +0x77 and +0x82 are now nonzero in every checked sample (Autosave.gms/nom.gms show 0x07 and 0x4d; p.gms/q.gms show 0x07 and 0x90; g.gms shows 0x07 and 0xa3), while relative +0x97 and +0xc5 remain 0. The compared 1.05 save set is tighter now too: Autosave.gms and nom.gms cluster together on Alternate USA.gmp with +0x82 = 0x4d, g.gms carries Spanish Mainline.gmp with +0x82 = 0xa3, and p.gms/q.gms cluster on Southern Pacific.gmp with +0x82 = 0x90; across all five files the same inferred analogue lane at +0x77 stays fixed at 0x07, while the same map- or scenario-sensitive tail word at +0x80 tracks those 0x4d/0xa3/0x90 byte lanes (0x364d0000, 0x29a30000, 0x1b900000). The leading dword at +0x00 also splits the same corpus, with Autosave.gms alone at 3 and the other four checked 1.05 saves at 5. That is enough to say the wider save corpus does contain nonzero candidates for two of the atlas-tracked profile lanes, and that one of them varies coherently with the loaded scenario family, but not yet enough to claim that the 1.05 block reuses the exact same semantic field assignments as the classic one. The loader-side family split is tighter now too: p.gms and q.gms no longer live under a generic fallback; their save headers now classify as one explicit rt3-105-scenario-save branch with preamble words 0x00040001/0x00018000/0x00000746 and the early secondary window 0x00130000/0x86a00100/0x21000001/0xa0000100, while g.gms now classifies as a second explicit rt3-105-alt-save branch with the different preamble lane 0x0001c001/.../0x00000754 and early window 0x00010000/0x49f00100/0x00000002/0xa0000000. That branch now carries the same bootstrap, anchor-cycle, named 1.05 trailer, and narrow profile-block extraction path as the other 1.05 saves. The bridge just below that trailer is now explicit too: the common 1.05 save branch carries selector/descriptor 0x7110 -> 0x7801 in Autosave.gms and 0x7110 -> 0x7401 in nom.gms, and both still reach the same first later candidate at span_target + 0x189c, well before the packed profile at span_target + 0x3d48; the rt3-105-alt-save branch instead carries 0x54cd -> 0x5901 and its first later candidate lands at packed_profile + 0x104, essentially on the profile tail; the scenario-save branch still diverges locally with 0x0001 -> 0x0186 and never enters that later 0x32c8-spanned bridge at all. The common-branch bridge payload is narrower now too: both checked base saves expose the same 0x20-byte primary block at 0x4f14 followed by the same denser secondary block at 0x671c, 0x1808 bytes later, and that secondary block now appears to run intact up to the packed-profile start at 0x73c0 for a total observed span of 0xca4 bytes. The trailing slice of that secondary block is now typed one level further: a small header at secondary+0x354 carries the observed stride 0x22, capacity 0x44, and count 0x43, followed by a fixed-width 67-entry name table starting at secondary+0x3b5 and running through names like AluminumMill, AutoPlant, Bakery, Port00..11, and Warehouse00..11, with a short footer (dc3200001437000000) after the last entry. The trailing per-entry word is now surfaced too: most entries carry 0x00000001, while the currently observed zero-trailer subset is Nuclear Power Plant, Recycling Plant, and Uranium Mine. That footer is tighter now too: it parses directly as 0x32dc, 0x3714, and one trailing zero byte, so the shared map/save catalog currently ends on the same two grounded late-rehydrate progress ids that the classic staged-profile band already exposed. The strongest structural read is therefore that the entire 0x6a70..0x73c0 catalog region is shared verbatim between Alternate USA.gmp and the derived Autosave.gms, not rebuilt independently during save. Combined with the earlier grounded record-layout work under 0x00437743, 0x00434ea0, and 0x00434f20, the current safest semantic read is that this shared catalog is the bundled source form of the scenario-side named candidate-availability table later mirrored into [state+0x66b2], with each entry's trailing dword now reading as the same availability override bit later copied into [candidate+0x7ac]. The loader-side coverage is tighter now too: the same table parser now attaches both to the common-save bridge payload and directly to the fixed source range in .gmp files and the non-common rt3-105-scenario-save / rt3-105-alt-save branches. That makes the scenario variation explicit instead of anecdotal. Alternate USA keeps only three zero-availability names in this table (Nuclear Power Plant, Recycling Plant, Uranium Mine), Southern Pacific widens the zero set to twelve (AutoPlant, Chemical Plant, Electric Plant, Farm Rubber, FarmRice, FarmSugar, Nuclear Power Plant, Plastics Factory, Recycling Plant, Tire Factory, Toy Factory, Uranium Mine), and Spanish Mainline widens it again to forty-two, including Bauxite Mine, Logging Camp, Oil Well, Port00, and the Warehouse00..11 run while also flipping Recycling Plant back to available. The header lanes just ahead of the table vary coherently with those scenario branches too: Alternate USA carries header_word_0 = 0x10000000, Southern Pacific carries 0x00000000, and Spanish Mainline carries 0xcdcdcdcd, while the structural fields from header_word_2 onward remain stable (0x332e, 0x1, 0x22, 0x44, 0x43) and the 9-byte footer still decodes as 0x32dc, 0x3714, 0x00 in all three checked maps. A wider corpus scan over the visible .gmp/.gms files makes those two anonymous header lanes less mysterious too: the parser currently sees only three stable (header_word_0, header_word_1) pairs across 79 files with this table shape, namely (0x00000000, 0x00000000), (0x10000000, 0x00009000), and (0xcdcdcdcd, 0xcdcdcdcd). The zero-availability count varies widely underneath the first and third pairs (0..56 under the zero pair, 14..67 under the 0xcdcdcdcd pair), so those two lanes no longer look like counts or direct availability payload; the safest current read is that they are coarse scenario-family or source-template markers above the stable 0x332e/0x22/0x44/0x43 table header, with 0xcdcdcdcd still plausibly acting as one reused filler or sentinel lane rather than a meaningful numeric threshold. Current exported disassembly notes still do not ground one direct loader-side or editor-side consumer of header_word_0 or header_word_1 themselves, so that family-marker read remains an inference from corpus structure rather than a named field assignment. The new loader-side compare command makes the save-copy claim sharper too: for the checked pairs Alternate USA.gmp -> Autosave.gms, Southern Pacific.gmp -> p.gms, and Spanish Mainline.gmp -> g.gms, the parsed candidate-availability table contents now match exactly entry-for-entry, with the only reported differences being the outer container family (map vs save) and source-kind path (map-fixed-catalog-range vs the save-side branch). has the explicit companion world_refresh_selected_year_bucket_scalar_band 0x00433bd0, which rebuilds the dependent selected-year bucket floats after the packed year changes; and then rehydrates the named locomotive availability collection at [world+0x66b6] through locomotive_collection_refresh_runtime_availability_overrides_and_usage_state 0x00461e00. That locomotive-side restore is tighter now too: its tail explicitly re-enters scenario_state_refresh_cached_available_locomotive_rating 0x00436af0, which rebuilds one cached available-locomotive rating at [state+0x4cbe] from the current year plus the strongest surviving available locomotive-side rating scalar [loco+0x20], and the tiny query sibling 0x00434080 is now bounded as the shell-side clamped read helper over that same cached field, with the grounded shell-side reader later bucketing that value against 40/50/70/85/100. The same rehydrate band also refreshes the live structure-candidate filter and year-visible counts through structure_candidate_collection_refresh_filter_and_year_visible_counts 0x0041e970, rebuilding the paired per-slot bands at [candidates+0x246] and [candidates+0x16e] and the aggregate counts at [candidates+0x31a] and [candidates+0x242]; the same late checkpoint also re-enters placed_structure_collection_seed_candidate_subtype2_runtime_latch 0x00434d40, which seeds runtime dword [candidate+0x7b0] across subtype-2 candidate records before the later world-wide reactivation sweep. That checkpoint also now has an explicit shell-facing scalar publisher: world_publish_shell_controller_progress_scalar_from_year_thresholds_or_selector_overrides 0x004354a0 writes one clamped 0..255 value into the current shell presentation object, sourcing it either from the shell selector override pairs or from the scenario-side year-threshold band rooted at [state+0x3a/+0x51/+0x55/+0x59/+0x5d/+0x61]; and just ahead of the later scenario-side recipe rebuild, the same band also re-enters scenario_state_ensure_derived_year_threshold_band 0x00435603, which only falls into its heavier rebuild body while [state+0x3a] < 2 and otherwise leaves the derived year-threshold companion slots [state+0x51/+0x55/+0x59/+0x5d/+0x61] unchanged. The neighboring late status checkpoints around progress ids 0x196 and 0x197 also share one explicit stage gate now: world_query_global_stage_counter_reached_late_reactivation_threshold 0x00444dc5 compares the global counter 0x00620e94 against threshold 0x9901, and the two current callers use a negative result to clear [world+0x39] before the broader world and shell reactivation sweep. The later reactivation tail is tighter now too: it includes the region-center world-grid flag reseed pass 0x0044c4b0, which clears bit 0x10 across the live grid and then marks one representative center cell for each class-0 region through 0x00455f60; its immediate sibling 0x0044c450 then reruns placed_structure_rebuild_candidate_cargo_service_bitsets 0x0042c690 across every live grid cell. The small secondary-raster premark helper 0x0044c570 is bounded now too: it only admits cells whose current raster byte has no bits in mask 0x3e and whose parallel class query 0x00534e10 is false, then rewrites that masked class field to 0x02 and widens the same cached bounds-and-count band [world+0x21c6..+0x21d6]. The next helper 0x0044ce60 scans the secondary raster at [world+0x2135] for cells with any bits in mask 0x3e, caching min/max bounds plus a marked-cell count in [world+0x21c6..+0x21d6]; the larger sibling 0x0044c670 then consumes those cached bounds to normalize the same raster and rebuild one dependent overlay/cache surface before the later route-style rebuild, shell-window, and briefing branches. That overlay side is tighter now too: after 0x0044c670 resolves scaled surface dimensions through 0x00534c50, it walks one local 3 x 32 sample lattice through the static offset tables at 0x00624b28/0x00624b48, keeps only secondary-raster classes 4..0x0d, folds several interpolated 0x0051db80 samples into one strongest local score, writes packed overlay pixels into the staged surface buffer, and only then publishes that staged overlay through 0x00534af0. The lower helper layer under that overlay pass is tighter now too: 0x00534e10 is the reusable secondary-raster class-set predicate for classes 1/3/4/5, 0x00534e50 is the smaller neighboring class-subset predicate for 1/4, 0x00534ec0 covers 2/4/5, 0x00534f00 covers 3/5, 0x00534e90 is the marked-bit query over the same 3-byte cell family, and the nearby local counter 0x0044bdb0 is now bounded as the 8-neighbor count companion for that same 2/4/5 subset, walking the shared 0x00624b28/0x00624b48 offset tables and re-entering 0x00534ec0 on each bounded neighbor cell. The first caller cluster around 0x0044bf9d..0x0044c37b therefore reads as a secondary-raster neighborhood service band rather than a generic map scan. 0x00533e70 and 0x00534160 are the coarser siblings over the overlay table at [world+0x1685]: the first clears coarse chunk objects across one clamped rectangle, while the second ensures one chunk object and seeds local marks through its deeper stamp helper. One level up, the neighboring rect owner 0x005374d0 now reads as the shared secondary-overlay refresh pass: it reruns the local sample and unsigned-word reducers 0x00536230/0x00536420, rebuilds the signed vector byte planes through 0x00536710, and then rebuilds the multiscale support surfaces through 0x00533890, whose inner reducers now explicitly target the packed sample-triplet buffer plus the float and unsigned-word support planes rooted at the five-entry per-scale families [world+0x15f1..+0x1601], [world+0x1605..+0x1615], and [world+0x1619..+0x1629]. The setup side of that same family is tighter now too: 0x005375c0 is the shared ensure-and-seed owner that allocates the sample, sidecar, mask, raster, vector, and coarse-cell tables together; crucially, it seeds [world+0x1655] with byte 0x02 and [world+0x1659] with byte 0x01, which closes the default-fill split. The local component-walk owner under the same neighborhood band is tighter now too: 0x0044c200 allocates a temporary width*height visit bitmap at 0x0062c128, seeds one class-2/4/5 starting cell, derives an initial direction index through the remap table 0x005ee5d4, and then fans into the deeper recursive walker 0x0044be20. That deeper walker widens dirty bounds [world+0x21ad..+0x21b9], stamps one companion-word orientation lane through 0x005ee5cc, reuses 0x00534ec0 plus 0x0044bdb0 to filter admissible neighbors, tracks temporary visitation in 0x0062c128, and then applies the local byte-1 edge-bit 0x04/0x08 updates before returning. So the 0x0044bf9d..0x0044c422 cluster now reads as a real connected-component walk plus edge-flag refresh layer over the secondary raster rather than only a loose group of local neighbor counters. The adjacent mutation strip is tighter now too: 0x0044dcf0 refreshes companion-word bit 0x200 in one local rectangle by checking whether any neighbor belongs to class set 2/4/5, while 0x0044df10 clears three local sidecar byte planes, demotes class 4 to 1 and class 5 to 3, and then reruns that marked-bit refresh over the surrounding +/-1 window. One level up, 0x0044e500 is the rect-wide owner that recomputes byte-1 edge bits 0x04/0x08 for class-2/4/5 cells, dispatches 0x0044df10 on incompatible local patterns, and finally consumes the pending global seed pair at [0x006d1304+0x78/+0x7c] through 0x0044c200. The shell-side owner of that pending pair is tighter now too: [0x006d1304] is the live PaintTerrain.win shell singleton while the callback-heavy side also keeps a second rooted pointer at 0x006d1334; the tool constructor snapshots the broader terrain-paint state into both families while the world-side raster owner still only consumes [0x006d1304+0x78/+0x7c] as one pending component-seed pair. Its radial sibling 0x0044e7d0 is narrower: after validating world-space coordinates through 0x00414bd0, it stamps class-2 marks into the secondary raster by walking one clamped bounding box and admitting cells only when the radial falloff helper 0x0051db80 stays positive before re-entering 0x0044c570. The two small support predicates under that same strip are now explicit too: 0x00414bd0 is the float grid-bounds gate, and 0x00449df0 is the integer rectangle clamp-and-validity helper shared by the local mutation owners. One level up, the broader rect-scoped owner is tighter now too: world_rebuild_secondary_raster_derived_surface_and_companion_planes_in_rect 0x0044e940 first reclamps the caller rectangle through 0x00449df0, reruns the local edge-refresh owner 0x0044e500, lazily ensures one presentation target through 0x0051f090/0x00534910/0x00534920/0x00534930, and then resolves scaled target dimensions through 0x00534c50 before allocating one temporary width*height mask. Its main scan then walks the live secondary raster [world+0x165d] through the same class predicates 0x00534e10/0x00534e50/0x00534f00/0x00534ec0: class-1/3/4/5 cells force 0xff into the four sidecar byte planes [world+0x1631..+0x163d], while the broader per-cell pass writes packed values into the ensured target through 0x00534730 and also updates nibble lanes at byte offsets +0x2 and +0x5 inside the same three-byte secondary-raster cell family. After the publish it notifies the shell owner at 0x0062be68, re-enters 0x00449f80 and 0x004881b0, frees the temporary mask, expands the caller rectangle by dirty bounds [world+0x21ad..+0x21b9] through 0x00536710, and finally seeds companion byte [world+0x162d] with 0xc4 on cells selected from mask plane [world+0x1655]. So the 0x0044e500 -> 0x0044e940 band is now a real derived-surface and companion-plane rebuild family rather than only a loose collection of local raster mutations. The local evidence now also supports a stronger negative conclusion: unlike [world+0x1655], that second mask plane is not part of the actively rebuilt runtime overlay path, and in the grounded local corpus it behaves only as a separately seeded, cleared, and persisted sibling plane. One level lower, the base-plane allocator 0x00532c80 now reads more cleanly too: it is the narrower owner that clears [world+0x15e1], optionally applies the current grid dimensions, allocates the base float-summary plane [world+0x1605], the four sidecar byte planes [world+0x1631..+0x163d], both one-byte mask planes [world+0x1655/+0x1659], and the packed secondary raster [world+0x165d], then seeds those planes with the same 0x02/0x01/0x00 default split. The load-side owner for those same planes is tighter now too: the constructor thunk 0x0044e910 immediately feeds the heavier payload body 0x0044cfb0, which reads the rooted chunk families 0x2ee2/0x2ee3/0x2ef4/0x2ef5/0x2ef6/0x2ee4/0x2ee5/0x2f43/0x2f44, allocates the core world-grid and secondary-raster arrays [world+0x2129..+0x2141] plus the route-entry collection 0x006cfca8, initializes every grid-cell record through 0x0042ae50, and only then hands off into world_compute_transport_and_pricing_grid 0x0044fb70, the neighboring presentation refresh 0x00449f20, and the shell-mode pulse 0x00484d70. So the 0x0044e910 -> 0x0044cfb0 load side is now bounded as the heavy world-grid and secondary-raster bundle-load body rather than just another anonymous constructor tail. One level higher again, the broader world-presentation reinitializer 0x00537e60 now sits above that base allocator and the larger support-family ensure path 0x005375c0: it stores the live grid dimensions, hard-resets the whole overlay runtime family through 0x00532590, reinitializes the secondary-overlay family for those dimensions, and then republishes the neighboring overlay constants and support owners used by both the world-side reattach branch and the .smp restore-side presentation rebuild path, including several owners that all funnel through the shared static-template slot allocator 0x00532ad0 over the local 0x100 pointer band at [world+0x08]. Those neighboring owners are tighter now too: 0x00535070 is the small primary overlay-surface-or-template setup owner, while 0x005356e0 and 0x00535890 seed two larger static-template slot bands rooted at [world+0x1568/+0x156c/+0x1574/+0x1578] and [world+0x1560/+0x1564] respectively; the remaining heavier sibling 0x00535430 now reads as a shared four-slot overlay-surface rebuild owner that resamples one source or fallback descriptor into a short local slot strip above [world+0x155c]. The tail of that same reinitializer is tighter now too: after the larger support-family setup it seeds one seven-entry default overlay companion set through 0x005373b0, whose inner allocator 0x00535950 populates the local 0x1b-entry slot table from the static template rows 0x005dd300..0x005dd378. The lifecycle side is tighter in the same way now: 0x00536044 is the shared teardown owner that frees those same three five-entry support families together with both mask planes, the packed secondary raster, the vector-byte planes, the local staging buffer, and the neighboring sidecar or coarse-cell tables. The remaining base-float lane is tighter too: the larger rebuild owner 0x00538360 now clearly writes one base float-summary field into [world+0x1605], clears both one-byte mask planes, and then only repopulates the primary mask plane [world+0x1655] for the qualifying class-1 interior cells before re-entering 0x00532d90 to normalize that base float-summary plane globally and 0x00532f60 to expand positive cells through one caller radius. That asymmetry is now enough to close the local semantic edge: [world+0x1655] is the actively rebuilt primary overlay mask, while [world+0x1659] is only the separately seeded and persisted secondary mask sibling with no comparably grounded distinct read-side consumer. The only grounded getter call to its root accessor 0x00533b60 is the shell staging branch at 0x00525bad, and that branch immediately discards the returned pointer. The bundle side is now explicit too: .smp save-load treats the two mask planes as separate payloads with chunk ids 0x2cee for [world+0x1655] and 0x2d51 for [world+0x1659], while the neighboring 0x2d49/0x2d50 branches are the separate packed secondary-raster import lanes rather than alternate consumers of the second mask plane. So, in the mapped local code, 0x1659 is best treated as a persisted compatibility or seed-state sibling, not as a second actively consumed runtime overlay mask. The event side is tighter too: that 0x00433130 pass in turn materializes each live event record through scenario_event_refresh_runtime_record_from_packed_state 0x0042db20. Current shell-side xrefs now tighten that event branch too: the first rebuilt linked row family under 0x0042db20 aligns with the standalone condition list later queried by EventConditions.win, while the second rebuilt family aligns with the four grouped effect lists later deep-copied through scenario_event_clone_runtime_record_deep_copy 0x0042e050 during event duplication and effect staging. The condition side is tighter now too: the tiny helper cluster 0x0042df30/0x0042df70/0x0042dfb0/0x0042dff0 is no longer just "some adjacent list scans". Current evidence bounds it as four predicates over the standalone 0x1e-row condition list, testing class bits 0x01, 0x02, 0x04, or any of those bits in the static table 0x005f3e04 + id*0x81, with special fallback checks through event fields [event+0x7f9], [event+0x7fa], and [event+0x7f0] == 0x63. The shell side is tighter too: vtable slot 0x005d0cd8 now binds shell_event_conditions_window_handle_message 0x004d59e0, and vtable slot 0x005d0cf8 binds shell_event_effects_window_handle_message 0x004d7060. The effects side is tighter too: the lower helper trio is no longer anonymous. 0x004d5d00 now reads as the effect-type selector refresh under control family 0x4fb2, 0x004d5f50 reads as the selected effect parameter-row repaint, 0x004d6090 is the heavier staged-effect editor refresh over the 0x4fc7/0x4fce/0x4ff6/0x4ff9/0x4ffc/0x5041/0x5044/0x5046/0x5047 bands, and 0x004d67f0 commits the current editor state back into the staged effect row at [this+0x78]. The verb side is tighter now too: shell_open_event_conditions_modal_and_return_result 0x004d9dc0 and shell_open_event_effects_modal_and_return_result 0x004d9e40 are the shared modal openers above the two editor windows; 0x004da640, 0x004da700, and 0x004d9ed0 now read as the add, edit, and remove verbs for standalone condition rows; 0x004da7c0, 0x004da860, and 0x004da920 are the matching add, edit, and remove verbs for grouped effect rows; and 0x004d8120 is now the heavier condition-row list panel refresh those condition-side verbs re-enter after mutation. The conditions-side refresh split is tighter too: 0x0042d700 aggregates standalone condition-list class or modifier flags, 0x0042d740 aggregates grouped effect-row type flags for one selected grouped list, 0x004d9970 owns the condition-class summary and grouped-row status bands, 0x004d77b0 owns the grouped summary-band affordance gate for 0x4fed..0x4ff0 when selector 0x5000 lands on 0x5002, 0x004d9d10 owns the smaller grouped-effect territory-target affordance on control 0x500b, 0x004d9f50 owns the selected-event mode strip and summary text panels, and 0x004d9390 is the mode-dependent detail-row switch beneath that strip. 0x004da0f0 is tighter too: selector 0x5001 now has the strongest current RT3.lng fit as the condition-side Test against... mode above 0x004d9970, while selector 0x5002 has the strongest current fit as the grouped-effect-side Apply effects... mode. That 0x5002 branch now clearly builds control 0x5014 from RT3.lng 1160..1164 as to the company/player/player (i.e. chairman)/territory for which the condition is TRUE before enabling the adjacent 0x5005, 0x500a, and 0x5014..0x501c family. The strongest current RT3.lng fit for the remaining visible target-scope strip is now 0x5015 = to the whole game, 0x5016..0x5018 = to all/human/AI companies, 0x5019 + 0x500b = to territories, and 0x501a..0x501c = to all/human/AI players; the grouped effect-row type mask matches that split directly through bits 0x08, 0x01, 0x04, and 0x02. The selected-event strip is tighter now too: 0x004db120 is the broader selected-event repaint and navigation refresh above those smaller helpers, 0x004db520 and 0x004db5e0 are the previous and next selected-event stepping verbs, 0x004db8b0 is the add-or-clone event modal helper, 0x004dba90 is the rename verb, 0x004d9360 is the delete verb, 0x004db6a0 is the live selected-event id setter behind control 0x4e84, and 0x004db6f0 is the callback-binding plus pending-selection bootstrap path that seeds the strip during window bring-up. The larger dispatcher at 0x004dbb80 now makes the strip explicit: 0x4e85..0x4e8a are previous, next, add blank, clone selected, rename, and delete event, while the later grouped band commits current summary state through 0x004d8d50 before changing grouped selector [this+0x9c] via 0x004dbf93. The selection bootstrap side is tighter too: 0x004daf40 is now the placeholder reset helper for the selected-event summary controls 0x4eaf, 0x4eac, 0x4ed9, 0x4edb, and 0x4fdf..0x4fe2. The grouped target-scope side is tighter too: 0x004d8ea0 now reads as the commit helper for current selected-event text panels before selection or grouped-action changes, 0x004d8d50 now records the hidden selector family 0x5006..0x500e -> 0..8, and 0x004dab60 projects that ordinal one-to-one onto the visible grouped-effect target-scope display strip 0x5014..0x501c. That split is firmer now: 0x5006..0x500e are the canonical hidden selectors that get stored into [event + group + 0x7fb], while 0x5014..0x501c are the visible mirror rows republished from that same ordinal rather than a second independently named selector family. The grouped row and stored-summary refresh side is tighter too: 0x004d88f0 is now the selected grouped-effect row-list renderer for 0x4ed5, formatting the grouped 0x28-byte rows through RT3.lng 1154..1159, and 0x004da9a0 is the current grouped-summary-state republisher that reloads 0x500a, 0x500b, and visible action selection 0x5014..0x501c from [event + group + ...] before tailing back into 0x004da0f0, 0x004dbfca as the grouped target-scope mode selector that persists the chosen control id into 0x00622074, with 0x5001/0x5002 now strongest-fit as Test against... and Apply effects..., 0x004dbeeb as the pending shared summary-text triplet publish helper for 0x4eac/0x4ed9/0x4edb, 0x004d91e0 as the selected-event summary-header and grouped-mode commit helper above 0x004d8d50, and 0x004dbe7a as the narrower 0x4ec6/0x4ec7 choice-event single-player-only warning modal branch rooted at RT3.lng 3887. The remaining gaps on this lane are narrower again because the grouped-band 0x4dc09c table now closes one earlier overclaim: controls 0x5001/0x5002 are the only 0x4fed..0x501c entries that route into 0x004dbfca on the 0xcf side, while visible rows 0x5014..0x501c only route to the smaller 0x004d9d10 affordance path and the rest of 0x4ff1..0x5013 are default no-ops. The open question is therefore no longer whether those visible target-scope rows are direct selector verbs; current evidence says they are not. The local slot records are rooted at [world+0x69d8], [slot+0x01] polarity and the external role gate at [world+0x0bc3+slot*9] are now grounded, and [slot+0x03] now looks like the distinguished primary-human-seat marker because current grounded writes seed it only on slot zero and later logic moves it solely by whole-record compaction. The open question is no longer whether the seeded trio lands in the visible shell company roster; current evidence says it does, and ordinary Start New Company now looks like a fresh-company allocator through start_new_company_dialog_commit_create_company and start_new_company_request_create_company, not like the path that claims one of the seeded named railroads. The immediate post-roster station branch is now clearly separate: current grounded resource names and handlers put mode 8 on StationDetail.win, mode 5 on StationList.win, and the subordinate selector helper on StationPick.win. The company-side ownership question has therefore moved down a layer rather than staying open. We now have a recovered CompanyDetail.win owner family through shell_company_detail_window_refresh_controls, shell_company_detail_window_construct, and shell_company_detail_window_handle_message; the same owner now has one broader bounded read-side lane too, because control 0x9470 uses shell_company_detail_render_financial_history_panel to draw the five-step Revenue or Expenses or Interest or Profit or Lifetime strip, sibling control 0x9471 reuses shell_format_company_financial_summary_card through shell_company_detail_render_company_summary_card, controls 0x947d and 0x947e now ground a bond maturity and repay panel through shell_company_detail_render_bond_maturity_and_repay_panel, control 0x9488 now grounds the debt or credit or rate summary block through shell_company_detail_render_debt_credit_and_rate_summary_panel, control 0x948a now grounds the share-value and dividend-payout block through shell_company_detail_render_share_value_and_dividend_summary_panel, while the broader six-row per-share stock-data family is now bounded under shell_format_company_stock_data_panel, and the adjacent territory selector lane is bounded through shell_company_detail_select_territory_access_row, shell_company_detail_render_territory_access_row, shell_company_detail_sync_selected_territory_from_picker, and shell_company_detail_refresh_selected_territory_access_summary; the first finance-action layer beneath it is bounded through the bond, stock-issue, stock-buyback, and dividend-rate helpers; the territory-access side is bounded too through shell_company_detail_refresh_selected_territory_access_summary, shell_company_detail_buy_territory_access_rights_flow, and the underlying company access-rights helpers; and the full takeover and merger vote-result lane is now grounded through shell_resolve_chairmanship_takeover_vote_and_commit_outcome, shell_present_chairmanship_takeover_vote_outcome_dialog, shell_resolve_merger_vote_and_commit_outcome, and shell_present_merger_vote_outcome_dialog. The remaining company-side uncertainty is therefore narrower than before: the broader support and valuation side is now tighter too because company_compute_cached_recent_per_share_performance_subscore, company_compute_five_year_weighted_shareholder_return, and company_compute_public_support_adjusted_share_price_scalar bound the recent per-share performance and investor-support/share-price blend beneath those vote resolvers; the recent per-share feeder now has a grounded four-lane tail too, with current partial-year weight (5 * [world+0x0f]) - 5, prior full-year weights 48/36/24/12 on 0x1f/0x1e, dividend non-decline pair weights 9/8/7/6 on 0x20, lane weights 40/10/20/30, the startup age ramp 0/0/0/100 -> 25/25/35/100 -> 50/50/65/100 -> 75/75/85/100 -> 100/100/100/100, a strongest-lane *1.25 boost, a weakest-lane *0.8 reduction, and separate bounded-intermediate versus final difficulty applications under 0x005f33b8; the next consumer 0x00424fd0 is also tighter now, with the young-company interpolation against [company+0x57], caller pressure clamped to [-0.2, 0.2], one (shares / 20000)^0.33 share-count growth term, and the later threshold ladder 0.6 / 0.45 / 0.3 / 1.7 / 2.5 / 4.0 / 6.0 before the issue-0x37 multiplier, scenario_state_compute_issue_opinion_multiplier now bounds the next layer of optional company, chairman, and territory-specific opinion overrides on the active scenario state, and the broader stat-reader family around company_read_control_transfer_metric_slot and company_read_year_or_control_transfer_metric_value is no longer just a merger-premium helper. Current grounded callers show the same metric family feeding the annual shareholder-revolt and creditor-liquidation lane surfaced by localized ids 300..304, while the debt-side shell and bond lane now separately close 0x38 as Credit Rating and 0x39 as Prime Rate. That means the remaining gap is now mostly gone on the UI side too: issue 0x37 is already bounded to the same investor-confidence family as the equity-support and governance-pressure paths, and current grounded UI evidence still stops at the investor-attitude sentence family rather than one standalone caption. The calendar side is tighter now too: [world+0x15] is the absolute counter for the same mixed-radix 12 x 28 x 3 x 60 year-plus-subfield tuple packed by 0x0051d3c0 and unpacked by 0x0051d460, not just a vague “calendar-like” blob. The TrackLay.win family now clearly owns Lay single track. Lay double track. and Bulldoze as its three primary modes, its bridge selector, its wrapped frequency preferences, and a strongly aligned pair of Auto-Hide Trees During Track Lay and Auto-Show Grade During Track Lay toggles; the StationPlace.win family now clearly owns its six top-level category 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. The live auto-load boundary is tighter now too: hook-driven shell_transition_mode(4, 0) now completes old-mode teardown, reconstructs and republishes LoadScreen.win, and returns cleanly, but the later post-transition service ticks still keep [0x006cec78] = 0, [shell_state+0x0c] on the same LoadScreen.win singleton, and [LoadScreen.win+0x78] = 0 through at least counts 2..8. So the next runtime edge is no longer the old mode-4 teardown or publish band; it is the LoadScreen.win message owner 0x004e3a80 itself, because later service alone is not promoting the plain load screen into the separate startup-runtime object path. One later runtime probe did not actually reach that edge: the 0x004e3a80 hook installed, but the run never produced any ready-count, staging, transition, post-transition, or load-screen-message lines, only ordinary shell node-vcall traffic. So that result is now treated as a gate-or-cadence miss rather than as evidence against the LoadScreen.win message path itself. The newer shell-state service trace tightens it again: on a successful staged run the later service ticks do execute in mode_id = 4, but the 0x004e3a80 message hook still stays silent while the state remains frozen in the plain LoadScreen.win shape. So the next runtime boundary is now the shell-runtime prime call 0x00538b60 beneath shell_state_service_active_mode_frame 0x00482160, not the message owner alone. The first direct 0x00538b60 probe run is not trustworthy yet, though: it stopped immediately after the first shell-state service-entry line, before any ready-count or runtime-prime entry logs. So that result is currently treated as probe validation work, not as a real boundary move inside RT3. The static service branch is conditional too: 0x00482160 only enters 0x00538b60 when [shell_state+0xa0] == 0, so silence from the runtime-prime hook does not yet prove the shell stops before that call unless the service-entry logs also show the +0xa0 gate open. The newer run now closes that condition: [shell_state+0xa0] is 0, and the 0x00538b60 runtime-prime hook enters and returns cleanly. The newer run closes the next owner too: 0x00520620 shell_service_frame_cycle also enters and returns cleanly on the same frozen mode-4 path, and the logged fields match its generic branch rather than a startup-promotion lane ([+0x1c] = 0, [+0x28] = 0, flag_56 = 0, [+0x58] pulsed then cleared, and 0x006cec78 stayed 0). So the next runtime boundary under the same shell-state service pass is now one level deeper: the per-object service walker 0x0053fda0 beneath 0x00538b60. The newer run closes that owner too: it enters and returns cleanly while servicing the LoadScreen.win object itself, with field_1d = 1, field_5c = 1, and a stable child list under [obj+0x70/+0x74], and its first child-service vcall target at slot +0x18 stays 0x005595d0. Since 0x006cec78 still stays 0 through those clean object-service passes, the next runtime boundary is now the child-service target 0x005595d0, not the higher object walker. The newer child-service run narrows that again: the first sixteen 0x005595d0 calls are stable child lanes under the same LoadScreen.win parent, with [child+0x86] pointing back to the load-screen object, field_b0 = 0, and a split where earlier children carry flag_68 = 0x03 and return 4 while later siblings carry flag_68 = 0x00 and return 0. The static body matches that read too: 0x005595d0 is gated by 0x00558670 and then spends most of its work in draw or overlay helpers 0x54f710, 0x54f9f0, 0x54fdd0, 0x53de00, and 0x552560, so it now reads as another presentation-side service lane rather than the missing startup-runtime promotion. The widened allocator-window trace then reconciled the runtime with the static mode-4 branch one step further: the first transition-window allocation is 0x7c, which matches the static pre-construct 0x48302a -> 0x53b070 alloc exactly, and the later 0x111/0x84/0x3a/0x25... allocations all occur before LoadScreen.win construct returns, so they now read as constructor-side child or control setup. That means the allocator probe did not disprove the still-silent startup-runtime slice; it simply exhausted its log budget inside the constructor before the post-construct block. The later reset-at-return run is now the decisive one: after LoadScreen.win construct returns there are still no further allocator hits before publish and transition return, which matches the corrected jump-table decode because mode 4 does not own the 0x46c40 -> 0x4336d0 -> 0x438890 startup-runtime path.

  • 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. That copy side is tighter now too: the handler first enters 0x00420e00, which rebuilds the selected region's profile collection [region+0x37f], clones the source region's live label-weight entries when a source region is present, and otherwise reseeds a fixed default weight set through repeated 0x004206b0 calls. The no-source companion 0x00420ed0 now makes that split explicit: it rebuilds the same subcollection and then picks one of two fixed default label-weight sets based on region class dword [region+0x23e], using one all-0.2f family for nonzero-class regions and one class-0 family that starts with 0.3f before continuing with repeated 0.2f entries. The lower mutator 0x004206b0 then linearly scans the selected region subcollection by profile label, creates a new profile only when the copied weight is positive, removes an existing profile when the copied weight is non-positive, updates [entry+0x1e] otherwise, and refreshes the region's derived availability-summary bytes [region+0x2f6/+0x2fa/+0x2fe] through 0x00420410; map_editor_territory_panel_construct and the adjacent no-source companion 0x00420ed0 is tighter too: it rebuilds the same collection root [region+0x37f] but then seeds one of two fixed default profile-label sets directly through repeated 0x004206b0 calls, splitting by region class dword [region+0x23e]. Nonzero-class regions take one all-0.2f default set, while class-0 regions take a different set that starts with one 0.3f weight before continuing with repeated 0.2f entries. That makes 0x420ed0 the true class-split default-profile companion to the source-cloning helper at 0x420e00, rather than just more of the same editor copy path. 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 current local file-side result is now tighter too: the grounded recipe-book root at 0x0fe7 is preserved byte-for-byte across the checked map/save scenario pairs, so the loader can safely treat the twelve 0x4e1-byte books as preserved scenario payload rather than a drifting save-only band. A conservative summary probe now only reports per-book head signatures, raw cap dwords at +0x3ed, and five raw line summaries rooted at +0x3f1 so the file-side structure stays aligned with this grounded ownership. 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 internal indexing is tighter now too: the direct-supply lane indexes from [desc+0x1c], the demand or input lane uses that same resolved cargo id in the no-subrow branch, and the scaled production-output lane indexes each subordinate row directly from [desc+0x44+row*0x1c], with no post-resolution failure guard between the importer writes and the summary-bank updates. So the strongest current read is narrower than a full cargo-id decode: if the imported low-16 marker rows fail the exact matcher at 0x0041e9f0, the resulting 0 ids will still hit the first summary-bank bucket inside 0x00412650, but the semantic meaning of cargo id 0 itself remains ungrounded. 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 compare step tighter, the raw line lanes now split cleanly by scenario family while still preserving map->save identity inside each checked pair. Alternate USA.gmp and Autosave.gms match at the raw line-content level: books 0..4 keep mixed line areas, their line02 slots carry the recurring nonzero mode words 0x00110000, 0x000b0000, 0x000b0000, 0x00130000, and 0x00180000, and the same line02 slots also carry one recurring supplied token 0x000040a0; the neighboring line00/line01 slots carry the same recurring demanded token lanes such as 0x00010000, 0x72470000, 0x6f430000, 0x694c0000, and 0x694d0000. Southern Pacific.gmp and p.gms also match at the raw line-content level, but the same rooted line slots stay zero in the checked pair. Spanish Mainline.gmp and g.gms again match at the raw line-content level yet carry a distinct nonzero pattern: books 0..4 keep mixed line areas, line-level supplied tokens include 0x00170000, 0x00150000, 0x00004040, and 0x00004000, demanded tokens include 0x00010000, 0x68430000, and 0x6c410000, and the later line02 mode words stabilize at 0x00070000 then 0x00010000. So the loader can now safely treat these raw line lanes as preserved scenario payload with family-specific signatures, even though the exact cargo-id and mode-enum semantics still need separate grounding. One inference is tighter now too: when those demanded-token words are zero in the low 16 bits and printable in the high 16 bits, the byte order reads as short two-letter stems such as Gr, Co, Li, Mi, Ch, and Al, which fit the current scenario cargo-name families Grain, Corn, Livestock, Milk, Cheese, and Alcohol from RT3.lng; the runtime probe now exposes those only as probable ASCII stems, not as fully grounded cargo-id decodes. The supplied-token side is now bounded as a separate layout family rather than forced into that same stem model: the Alternate USA family uses one stable low-16 marker 0x000040a0 only in book00..04.line02, the Southern Pacific family leaves the supplied lanes zero in the checked pair, and the Spanish Mainline family splits between two high-16 numeric tokens 0x00170000 and 0x00150000 in book00/01.line01 plus the later low-16 markers 0x00004040, 0x00004000, and 0x00004040 in book02..04.line02. The probe now exposes those conservatively as token-layout classes high16-ascii-stem, high16-numeric, and low16-marker, without claiming that the non-stem numeric or marker families are decoded yet. One more structural layer is stable enough to name conservatively: the checked nonzero recipe rows repeatedly fall into four line-signature classes. Alternate USA books 0..4 all expose one demand-numeric-entry at line00 (0x00010000), one demand-stem-entry at line01 (Gr/Co/Li/Mi stems), and one supply-marker-entry at line02 (nonzero mode plus 0x000040a0). Spanish Mainline books 2..4 expose that same three-line pattern with Ch/Al stems and the 0x00004040/0x00004000 marker family, while books 0/1 only expose the earlier supply-numeric-entry form at line01. So the loader can now distinguish recurring row roles such as demand-stem versus supply-marker without pretending the marker payloads themselves are decoded. The importer-side branch map is tighter now too because local objdump over 0x00435630 shows that only nonzero mode dwords materialize into 0xbc runtime descriptors: mode 0 lines are skipped entirely, mode 1 enters the demand-only branch, mode 3 enters the dual demand-plus-supply branch, and every other nonzero mode falls into the supply-side branch. In the checked corpus that means the recurring demand-numeric-entry and demand-stem-entry rows in Alternate USA and Spanish Mainline are preserved scenario-side line records but do not become live runtime descriptors, while the later supply-marker-entry rows are the ones that actually reach the runtime import path. The runtime probe now exposes that directly as imports_to_runtime_descriptor plus one conservative runtime_import_branch_kind. The raw token windows beneath those branch labels are tighter now too. The checked mode-zero demand rows preserve string-bearing windows at line+0x1c, and the current probe shows those conservatively as prefixed ASCII previews such as ..Grain, ..Corn, ..Livestock, and ..Milk; local objdump over 0x0041e9f0 then shows the importer feeding the corresponding token buffer into an exact cargo-name matcher built over the live cargo collection at 0x0062ba8c. By contrast, the imported supply-marker-entry rows feed nonprintable windows such as .@... from line+0x08 through that same matcher, and the resolver path currently shows no special-case decoding for those marker forms. So the strongest static read is now: the stem-like demand rows preserve cargo-name text but are skipped because their mode is zero, while the nonzero imported marker rows are the live descriptor inputs yet likely fail exact cargo-name resolution unless another upstream transform exists. The wrapper layer above that query no longer looks like a hiding place for special treatment either. Local objdump now shows 0x00412960 simply summing the two supply-side floats returned by 0x00412650, while 0x004129a0 returns the single scaled production-output lane directly; neither wrapper checks for cargo id 0 after the query returns. The broader world-side accumulator at 0x0041e7be is tighter in the same way: it calls 0x00412650, requires all four returned channels to be positive before continuing, and only then scales those four channel values by one linked-instance count from 0x00413940 into caller-owned accumulators. So the current strongest read remains structural rather than semantic: unresolved marker rows can still propagate through the first bank bucket, but the first place that meaning matters is a normal positivity-gated cargo-channel consumer, not a dedicated null-cargo branch. The caller side is narrower than before too. The steady-state site bitset owner placed_structure_rebuild_candidate_cargo_service_bitsets 0x0042c690 starts its inner cargo loop at id 1 and only walks upward through the current live cargo count, so it never intentionally queries cargo id 0. The broader placed-structure sweep around 0x00452e60 tightens the same boundary from above: when the requested cargo id is nonzero it resolves the backing candidate and enters structure_candidate_supports_or_references_cargo_id, but when the requested id is exactly 0 it skips that cargo-reference helper entirely and falls through to a different linked-site or station-or-transit gate. Current local objdump now shows that bypass first requiring one subtype latch through the placed-structure vtable +0x70, then resolving the linked site id at [site+0x2a8] through the placed-structure collection 0x006cec20, and then forwarding that linked peer into the narrower predicate at 0x0047fd50. That narrower helper is tighter than before too: it resolves the linked peer's backing candidate through the peer site id at [peer+0x04], reads candidate class byte [candidate+0x8c], and returns true only for the first three class values 0/1/2 while rejecting 3/4 and anything above 4. So current local callers treat cargo id 0 as a nonstandard request bound to one linked-site reachability or classification side path, not one ordinary cargo lane they routinely probe. The vtable-+0x70 latch itself is bounded a bit better now too. It still lacks a direct field decode, but every local callsite we checked around 0x0040d230, 0x0040dba0, 0x0040dbf0, and 0x0040f670 uses that slot only as the precondition for touching [site+0x2a8] and the neighboring linked-site helpers 0x0047dda0, 0x0047fd50, and 0x004138b0. That makes the safest current read a linked-site-bearing or linked-site-capable latch, strongly aligned with the subtype-1 construction lane that is the only grounded writer of [site+0x2a8], rather than a broad cargo or route-style predicate. The neighboring maintenance pair tightens that linked-site read further. Local objdump now shows 0x0040dba0 and 0x0040dbf0 as complementary tiny helpers that each require the same vtable-+0x70 latch, resolve optional linked peer id [site+0x2a8] through 0x006cec20, forward that linked peer (or null) into 0x0047dda0, and then mirror opposite values into local byte [site+0x42] (0 for 0x0040dba0, 1 for 0x0040dbf0). The route-entry side beneath them is tighter too: 0x0047dda0 reads route-entry anchor id [peer+0x08], resolves that anchor through 0x006cfca8, and only dispatches one of two route-entry vtable calls when 0x0048a090(1) reports that all three anchor-slot dwords [entry+0x206], [entry+0x20a], and [entry+0x20e] are still -1. So the strongest current read is no longer just "linked-site capable" in the abstract: this latch consistently fronts the local linked-peer class gate 0x0047fd50, the paired [site+0x42] route-entry state toggles, and the later linked-peer collection sweep 0x004138b0, which keeps the cargo id 0 bypass path firmly on the linked-site route-anchor or classification side rather than on an ordinary cargo lane. One smaller ownership boundary is tighter too: byte [site+0x42] is not private scratch owned only by that pair. Local objdump shows tiny direct setters at 0x0040cbc0 and 0x0040cbd0 plus a raw getter at 0x0040cbf0, so the 0x0040dba0/0x0040dbf0 pair is writing one shared placed-structure state byte rather than inventing a route-entry-only scratch lane. One caution is tighter now too: there are later mode-gated reads at other addresses that also touch a +0x42 byte on their own object layouts, but current local evidence does not yet prove those are the same placed-structure owner family, so the safest current note keeps only the immediate 0x0040cbc0/0x0040cbd0/0x0040cbf0/0x0040dba0/0x0040dbf0 cluster grounded together. The vtable side sharpens that split too. A local .rdata scan shows 0x0040dba0 and 0x0040dbf0 each appearing exactly once, together with 0x0040cbf0, in one method table rooted at 0x005c8c50; the constructor chain is tighter now too, because 0x0040c950 installs that same table as one concrete placed-structure specialization above the common base table 0x005cb4c0, while 0x0040c970 tears the same specialization back down to the base before the temporary object is freed. By contrast the raw set or get trio 0x0040cbc0/0x0040cbd0/0x0040cbf0 also appears in several sibling tables such as 0x005c9750 and 0x005dd1f0. So the strongest current structural read is that byte [site+0x42] belongs to one broader placed-structure virtual interface, while the linked-peer route-entry toggles are one specialization-specific override pair inside that family rather than generic setters used by every sibling. One negative boundary is tighter now too: the raw token words in this recipe block do not look like the already grounded shell-side AnyCargo/AnyFreight/AnyExpress selector-table ids from 0x00621e04/0x00621e10, so the current best read is that these on-disk line tokens are not just copied UI selector ordinals or the same small express-side id family in another wrapper. 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, placed_structure_get_nth_candidate_id_with_local_service_metrics 0x0047e620 is the ordinal selector over that same visible candidate family, placed_structure_query_cached_express_service_class_score 0x0047e390 caches one parallel class score for the express family now strongly aligned with Passengers, Mail, and Troops, placed_structure_refresh_candidate_local_service_comparison_cache_against_peer_site 0x0047eb90 rebuilds one peer-site comparison cache over the same local-service inputs, and placed_structure_select_best_candidate_id_by_local_service_score 0x0047f910 is the best-hit selector above the direct and directional local-service query pair. Those site-side scores now have grounded shell read-side consumers too: shell_station_detail_format_freight_and_express_summary 0x00506be0 formats the visible Freight: %1 and Express: %1 lines in StationDetail.win, and the same station-detail family now has a deeper candidate-service lane: shell_station_detail_set_active_candidate_service_preview 0x00504ae0 stores the active (station id, candidate id) pair for the world-side preview scan, shell_station_detail_clear_active_candidate_service_preview 0x00504a90 tears that pair back down, shell_station_detail_update_candidate_service_entry 0x00504ba0 is the shell-side entry updater above that preview pair, shell_station_detail_format_candidate_local_service_summary 0x00504bea uses placed_structure_query_candidate_local_service_metrics together with localized ids 681, 682, and 2813 to build the visible candidate service text, shell_station_detail_build_to_from_haul_summary_widget 0x00505150 now grounds the paired To and From hauled-traffic strip widgets, shell_station_detail_present_to_from_haul_stats_popup 0x00504770 owns their click-through annual and lifetime hauled TO/FROM this station popup, shell_station_detail_refresh_nearby_structure_jump_rows 0x00505470 owns the five-row nearby-structure jump lane, and shell_station_detail_refresh_candidate_service_rows 0x00505760 is now the larger row-list owner that enumerates active candidate-service entries and wires shell_station_detail_update_candidate_service_entry into the per-row click path. shell_station_list_format_freight_and_express_availability_summary 0x00506e50 feeds the station-list summary %1 has %2 freight loads and %3 express loads available for hauling..., and the paired modifier helper shell_station_list_handle_center_or_rename_action 0x00506d50 owns the visible Shift-center and Ctrl-rename row actions. The report side is clearer as well: 0x004d3060 is the dedicated Stats - Trees constructor over map_editor_tree_stats_report, 0x004d3080 is the actual General Validation constructor over map_editor_general_validation_report, and the same page table also now grounds Stats - Cargo, Stats - City/Region, Stats - City Count, Event Variable Values, and the neighboring event-validation page. The remaining open editor edge is therefore mostly the deeper gameplay meaning of those site-side service scores and flag bits, not page ownership.

  • Station-detail overlay: the shell-side candidate preview pair now has a grounded world consumer too. world_render_station_candidate_service_map_overlay at 0x0043f640 reads the active (station id, candidate id) pair from 0x005ee4fc and 0x005ee500, scans the placed-structure collection, and then splits the legend by candidate mode. When the active candidate carries a nonzero route-style byte at [candidate+0x46], the overlay uses the heavier helper placed_structure_query_candidate_directional_route_overlay_summary at 0x0047e690 in both directions between the preview station and each scanned site and formats the resulting directional rows as 3874 Coming To %1 and 3875 Going From %1. When that byte is zero, the same overlay falls back to the direct local-service path through placed_structure_query_candidate_local_service_metrics and formats the two legend rows instead as 3876 Current Supply @ < %1 and 3877 Current Demand @ > %1. Empty directional lanes collapse to 3878 --None--, and one title lane falls back to literal All. Current disassembly no longer supports treating 3872 Already Connected by Another Company or 3873 Not Connected as direct overlay-body emits.

  • Station-detail overlay, corrected boundary: the neighboring connection-state note pair now appears to live in a city connection-bonus label formatter, not in 0x0043f640. That formatter is now bounded as city_site_format_connection_bonus_status_label at 0x004207d0: it directly chooses localized ids 3868 through 3873 after consulting the reusable city-peer scan city_connection_bonus_exists_matching_peer_site at 0x00420030. Separately, 3879 Out of Sync is grounded under the multiplayer preview dataset path instead: multiplayer_preview_dataset_service_launch_state_and_warn_out_of_sync at 0x0046b780 checks global 0x006cd91c, raises the Out of Sync shell status through 0x5386e0, and then continues through the wider multiplayer preview launch-state service. So the station-detail overlay currently owns only the Coming To, Going From, Current Supply, Current Demand, --None--, and All legend lanes.

  • Station-detail overlay, ownership side: one reusable site helper is grounded now too. placed_structure_query_linked_company_id at 0x0047efe0 resolves the current placed structure's linked instance through 0x0062b26c and returns its company id from [instance+0x276]; the adjacent city bonus formatter at 0x004207d0 compares that id against the active company selector before choosing whether a scanned site should carry 3871 Connected By Another Company or 3872 Already Connected by Another Company. The larger caller boundary is no longer open either: the first bounded announcement owner above this formatter family is now company_evaluate_and_publish_city_connection_bonus_news at 0x00406050, which re-enters the peer-route candidate builder at 0x004046a0 and later publishes one of the localized city-connection bonus news strings 2888, 2890, or 2921 through the shell news path.

  • Station-detail overlay, peer-selector side: the city bonus formatter no longer depends only on boolean peer existence. The companion helper city_connection_bonus_select_first_matching_peer_site at 0x00420280 is now grounded as the first-match selector paired with city_connection_bonus_exists_matching_peer_site: it walks the same city-peer candidate set, applies the same site-class table plus the narrower station-or-transit and linked-instance class-byte flags, and returns one representative matching peer site id instead of a boolean. city_site_format_connection_bonus_status_label reuses that selector after the note checks so it can recover one linked company context from the selected peer. The remaining open edge here is therefore above this formatter family, not inside the peer-scan pair itself.

  • Station-detail overlay, caller side: the reusable bridge between the status formatter and the company news lane is now bounded too. city_connection_bonus_build_peer_route_candidate at 0x004046a0 reuses city_connection_bonus_select_first_matching_peer_site with both selector flags forced on, samples the selected peer's derived coordinates through 0x0047df30 and 0x0047df50, and then either tries the shared heavy builder city_connection_try_build_route_with_optional_direct_site_placement 0x00402cb0 or falls back to the smaller wrapper city_connection_bonus_try_compact_route_builder_from_region_entry 0x00404640 before handing the result back to the company-side announcement sweep at 0x00406050. The score side of that announcement lane is tighter now as well: city_compute_connection_bonus_candidate_weight at 0x004010f0 provides the per-city opportunity weight, company_query_min_linked_site_distance_to_xy at 0x00405920 provides the nearest linked-site distance term, company_count_linked_transit_sites at 0x00426590 provides one of the company-side caps, company_compute_connection_bonus_value_ladder at 0x00425320 supplies the bounded company-side value scalar, and company_compute_prime_rate_from_issue39_scenario_baseline at 0x00424580 now bounds the shared prime-rate-side helper that this lane reuses beside the raw issue-0x39 total, scenario_state_sum_issue_opinion_terms_raw at 0x00436710 now bounds the raw additive issue-total helper beneath that term, and company_connection_bonus_lane_is_unlocked at 0x00427590 is the small boolean gate above the ladder. Wider governance and CompanyDetail xrefs now tighten slot 0x2b into the rolling net-profits lane reused by annual finance checks and a per-share/history formatter, while the report-history descriptor table now aligns raw slot 0x09 with the Income Statement fuel-cost lane surfaced by tooltip 1309. The wider result now reads more like recent net profits minus recent fuel burden than a governance-pressure term. That now also sharpens the annual finance lane at 0x00401c50: the first bankruptcy branch reads as sustained cash-and-debt stress over recent profits and fuel burden, the later fallback branch as a deeper -300000 cash / three bad years cleanup trigger, and the later stock-issue branch reads as a price-to-book-versus-coupon approval ladder rather than a generic support vote. The tail is cleaner now too: it compares total retired versus newly issued principal to choose the 2882..2886 debt headline family, then publishes 2887 separately from the accumulated repurchased-share count. The sibling news owner above the same city-pair route family is bounded now too: simulation_try_select_and_publish_company_start_or_city_connection_news 0x00404ce0 filters and scores candidate city entries, re-enters the same shared heavy builder through city_connection_try_build_route_between_region_entry_pair 0x00404c60 for the dense pair sweep and the final retry, and then publishes 2889 %1 has started a new company - the %2 or 2890 %1 has connected %2 to %3. through the shell news path. The remaining open edge on this branch is therefore narrower now: it is mostly whether 0x39 should be read as the narrower city-connection public-opinion lane or as part of a broader management-attitude family, not the ownership of the connection-bonus formatter, peer-route candidate path, or company news gate.

  • Station-detail overlay, route-list side: the neighboring helper placed_structure_append_unique_route_entry at 0x0047f010 is now grounded as the append-if-missing builder for the six-byte route-entry list rooted at [site+0x462] and [site+0x466]. That matters here because the directional overlay query at 0x0047e690 consumes the same list, so the remaining uncertainty is no longer list ownership. It is down to the exact semantics of each entry's u32 payload.

Next Mapping Passes

  • Resolve the owner-side callback roles behind the validated GameSpy packet branches, especially [route+0x9c], [route+0xa0], [route+0xa4], and [route+0xd4].
  • Determine whether any later world-mode branch beneath the frame owner bypasses the shell controller input path for non-cursor gameplay input, since the current grounded overlay and cursor helpers still reuse 0x006d4018.
  • Keep detailed pending-template or transport work scoped to the specific atlas edges that remain unresolved.