rrt/docs/control-loop-atlas.md

14 KiB

Control-Loop Atlas

This atlas is the high-level map for RT3 1.06. It is intentionally broader than the function map: each section explains who owns a loop, where it starts, what dispatches it, which state blocks anchor it, and where control is handed to neighboring subsystems.

CRT and Process Startup

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

Bootstrap and Shell Service Bring-Up

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

Shell UI Command and Deferred Work Flow

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

Presentation, Overlay, and Frame Timing

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

Map and Scenario Content Load

  • Roots: shell_map_file_entry_coordinator at 0x00445ac0, the first grounded world-entry branch world_entry_transition_and_runtime_bringup at 0x00443a50, shell_map_file_world_bundle_coordinator at 0x00445de0, reference-database setup via map_bundle_open_reference_databases at 0x00444dd0, and narrower loaders such as map_load_geographic_label_database and map_load_city_database.
  • Trigger/Cadence: shell tutorial launch, editor or detail-panel file actions, map-scenario open paths, and scenario-text export batch commands.
  • Key Dispatchers: shell_map_file_entry_coordinator, world_entry_transition_and_runtime_bringup, world_runtime_release_global_services, shell_map_file_world_bundle_coordinator, map_bundle_open_reference_databases, map_load_geographic_label_database, map_load_city_database, scenario_text_export_build_language_file, scenario_text_export_report_language_file, scenario_text_export_batch_process_maps.
  • State Anchors: shell-side file staging buffers at 0x0062bee0 and 0x0062bec4, shell and mode globals at 0x006cec74 and 0x006cec78, world object root 0x0062c120, map bundle state allocated through 0x00530c80, and geography tables rooted at 0x0062b2fc and 0x0062b268.
  • Subsystem Handoffs: the broad shell entry coordinator chooses between a full shell mode-transition and world bring-up path versus a sibling .smp world-state path. The heavier branch now appears to be the first true shell-to-gameplay handoff: it resets the prior world bundle, allocates the new 0x0062c120 world root from the staged filename, initializes multiple world-facing managers, and only then leaves later map content and runtime stepping to narrower helpers. The lower coordinator still fans into the live-world packaging branch at 0x00446240 or the reference-database bundle load at map_bundle_open_reference_databases, which in turn feeds shell preview panels scenario export tooling and later gameplay map state.
  • Evidence: function-map map/scenario rows, analysis-context exports for 0x00445ac0, 0x00445de0, 0x00443a50, 0x00434300, and 0x00444dd0, plus objdump string evidence for .gmp, .gmx, .gmc, .gms, .smp, and Quicksave.
  • Open Questions: the exact user-facing verb split between the .smp branch and the .gmp/.gmx/.gmc/.gms branch still needs tightening, but the remaining high-value 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.win session-event callback table around 0x00468de0..0x004691d0, plus the transport object and pending-template paths around 0x00597880..0x0059caf0.
  • Trigger/Cadence: event-driven session callbacks, registered-name updates, and repeated socket I/O service steps.
  • Key Dispatchers: session-event wrappers for actions 1, 2, 4, 7, 8; 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, status latch at 0x006cd974, pending-template list at [this+0x550], dispatch store at [this+0x55c], text-stream buffers at [this+0x108] and [this+0x114].
  • Subsystem Handoffs: bridges shell/UI status presentation, transport text streams, session state changes, and pending-template completion callbacks.
  • Evidence: function-map.csv, pending-template-store-management.md, pending-template-store-functions.csv.
  • Open Questions: unresolved request-id semantics for 1, 2, 4, and 7; the exact owner loop that repeatedly services transport I/O; and how multiplayer preview data ties back into the shell flow.

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, world_entry_transition_and_runtime_bringup at 0x00443a50, the frame-owned cadence simulation_frame_accumulate_and_step_world at 0x00439140, 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 post-bring-up gameplay service becomes recurring once a world root exists at 0x0062c120; elapsed wall-clock time is then accumulated and converted into one or more simulation-step quanta.
  • Key Dispatchers: shell_controller_window_message_dispatch, shell_input_apply_window_key_transition, shell_input_snapshot_dispatch_state, simulation_frame_accumulate_and_step_world, 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], nested dispatch counter [input+0xa90], global shell controller 0x006d4024, active world root 0x0062c120, accumulated leftover simulation time at [this+0x4c80], shell and mode globals at 0x006cec74, 0x006cec78, and 0x006cec7c, world manager collections at 0x0062be10, 0x006ceb9c, 0x006cfcbc, 0x006cec20, and 0x0062bae0, 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 shell consumers later snapshot that object through shell_input_snapshot_dispatch_state. After world entry the frame-owned cadence computes how much simulation time should elapse and repeatedly hands that budget into simulation_advance_to_target_calendar_point; the step helper then advances the world in coarse or fine increments, enters the periodic maintenance family when boundary conditions hit, notifies the live world root through 0x00450030, and returns to the frame owner for later shell-facing and world-facing follow-up work.
  • 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, world_entry_transition_and_runtime_bringup, simulation_frame_accumulate_and_step_world, simulation_advance_to_target_calendar_point, and simulation_service_periodic_boundary_work, plus analysis-context exports for the shell input cluster and the simulation cluster around 0x00439140, 0x0040ab50, and 0x0040a590.
  • Open Questions: whether gameplay continues to reuse this shell controller and input object path or hands off to a deeper world-mode input branch; the exact public semantics of the packed simulation tuple fields need tightening; and the save/load family still needs a cleaner user-facing split between autosave or package work and regular simulation stepping.

Next Mapping Passes

  • Clarify the user-facing split between the .smp branch and the .gmp/.gmx/.gmc/.gms branch under shell_map_file_entry_coordinator.
  • Identify the owner loop that repeatedly services multiplayer transport I/O and dispatch-store work.
  • Determine whether gameplay keeps using shell_controller_window_message_dispatch and the 0x006d4018 input object or hands off to a deeper world-mode input branch after world entry.
  • Ground the first gameplay save/load dispatcher and tie it back to the already-mapped .smp and live-world packaging branch.
  • Keep detailed pending-template or transport work scoped to the specific atlas edges that remain unresolved.