46 KiB
46 KiB
Map and Scenario Content Load
- Roots:
shell_map_file_entry_coordinatorat0x00445ac0, the larger active-mode profile ownershell_active_mode_run_profile_startup_and_load_dispatchat0x00438890, the shell-mode switchershell_transition_modeat0x00482ec0, the first grounded world-entry branchworld_entry_transition_and_runtime_bringupat0x00443a50,shell_map_file_world_bundle_coordinatorat0x00445de0, early reference-package save viamap_bundle_open_reference_package_and_serialize_early_world_datasetsat0x00444dd0, and narrower tagged collection owners such asgeographic_label_database_refresh_records_from_tagged_bundleandcity_database_entry_collection_refresh_records_from_tagged_bundle. - 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_package_and_serialize_early_world_datasets,geographic_label_database_refresh_records_from_tagged_bundle,city_database_entry_collection_refresh_records_from_tagged_bundle,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
0x0062bee0and0x0062bec4, shell and mode globals at0x006cec74and0x006cec78, world object root0x0062c120, map bundle state allocated through0x00530c80, and geography tables rooted at0x0062b2fcand0x0062b268. - Subsystem Handoffs: the shared
fileopt.windialog rooted at0x004dc670now looks like the shell-side selector above the two broad file coordinators. Its message handler sets0x006d07f8for the load or restore side or0x006d07ecfor the save or package side before the detail-panel transition manager routes intoshell_map_file_entry_coordinatororshell_map_file_world_bundle_coordinator. The former unresolved third flag at0x006d07f0is now accounted for too: it escapes into the standaloneSettingsWindow.winpath throughshell_open_settings_windowrather than another map or save verb. The broad coordinators now hand their interactive work through the sharedfilerqst.winhelper at0x004dd010, and that helper gives the extension split a firmer shape. The paired editor-map path is now grounded as.gmpthrough load mode4and save mode3. The remaining non-editor families are no longer anonymous either:.gmcis the campaign-scenario branch, backed both by the campaign-screen resignation prompt on0x006cec7c+0xc5and by the numbered%s%02d.gmcsave helper at0x00517c70;.gmxis the sandbox branch, backed by the shell-sideThe briefing is not available in sandbox games.restriction on0x006cec7c+0x82; and the default.gmsbranch 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.smpruntime-state branch instead. The auxiliary save-side mode11is tighter now too: it still maps to.gmt, but instead of looking like another gameplay save family it conditionally diverts into the same.gmtpreview-surface pipeline owned by the Multiplayer preview dataset object at0x006cd8d8, and only falls back to the normal reference-bundle path when that dataset object is absent. That fallback owner is tighter now too:0x00444dd0is not a generic database opener, but the early package-save prelude that seeds the shared stage/progress globals, opens one0x30d40bundle through0x00530c80, handles the localized failure modal0x0fda, and then serializes the first direct package band in a fixed order: chunks0x32c8/0x32c9, direct saves of[world+0x66be],[world+0x66b2], and[world+0x66b6], chunk0x32dc, the staged0x108profile block under0x3714/0x3715, thenworld_serialize_runtime_grid_and_secondary_raster_tables_into_bundle0x00449520for the early world-grid and sidecar-table band, thenaux_candidate_collection_serialize_records_into_bundle_payload0x00416a70for the direct0x0062b2fcsource-or-auxiliary record family, and only after that the neighboring reference and manager families beforeshell_map_file_world_bundle_coordinatorcontinues with the later tagged collections. That0x0062b2fcseam is tighter now too:0x00416a70first builds one temporary scored queue from each record's linked chain at[entry+0x04], writes one leading0xbabeheader, and then serializes the fixed fields, counted dword runs, optional byte payload, paired one-byte bands, and trailing dword for each queued record; the load-side companion isaux_candidate_collection_construct_stream_load_records_and_refresh_runtime_followons0x004196c0, which now clearly tails intoaux_candidate_collection_rebank_or_clone_records_by_availability_pass_and_refresh_owner_links0x00419230before the later world-load side continues, with destructoraux_candidate_collection_release_templates_queues_and_indexed_storage0x00419680. The fixed tail is explicit now too:0x00444dd0writes one direct dword from[world+0x19], one zeroed0x1f4-byte slab under0x32cf, closes the package, derives the preview path through0x00442740, and then conditionally emits the companion-image and companion-payload sidecars through0x00441f70and0x00442900when[world+0x66c8]and[world+0x66c9]are set. The shell-side mode owner above those file coordinators is clearer now too.shell_transition_modeno longer reads like a generic mode switch: its ABI is now grounded as athiscallwith two stack arguments because the body reads the requested mode from[esp+0x0c]and returns withret 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 the0x482fc6..0x482fffbranch only runs when it is nonzero and then releases the prior active-mode world through0x434300, falls through the neighboring no-op placeholder0x433730, and then reaches the common free path before clearing0x006cec78. The teardown owner itself is tighter now too:0x434300first destroys the two indexed world collections at[world+0x66b2]and[world+0x66b6], then releases the typed global roots0x0062b244,0x006cfcbc,0x0062be10,0x006ceb9c,0x0062c120,0x0062ba8c,0x006ada84,0x0062ba88,0x0062b2fc,0x0062b268,0x006cea4c, and0x006acd34in that order before it drains the shell-helper handle band[world+0x46a80..+0x46aa0], the variable owner band[world+0x46aa4], and the linked chains at[world+0x66a6]and[world+0x66aa]. The corresponding world-load allocation branch is tighter now too: inside0x00438c70,0x0062b2fcis allocated as a0xb8-byte object and then constructed throughaux_candidate_collection_construct_seed_globals_and_helper_bands_then_import_records0x0041aa50, which seeds the collection base, resets the neighboring constructor globals, builds the helper bands at[this+0x88/+0x8c/+0x90]through0x0041a990, and only then tails into the tagged import owner0x004196c0. The next two roots in the same load strip are now explicit too:0x0062ba8cis allocated and constructed throughstructure_candidate_collection_construct_and_stream_load_records_then_refresh_counts0x0041f4e0, which enters the tagged import owner0x0041ede0and then refreshes the aggregate filter/year-visible counts through0x0041e970; and0x006ada84is allocated and constructed throughlocomotive_collection_construct_and_stream_load_records0x00462520, which enters the linked-era locomotive import owner0x00461f10and then refreshes the live availability override band through0x00461e00. The same fan-out now also has explicit constructor ownership for the adjacent typed roots: the live company collection0x0062be10is constructed throughcompany_collection_construct0x00429950, the live profile/chairman collection0x006ceb9cis constructed throughprofile_collection_construct0x00477740, the live train collection0x006cfcbcis constructed throughtrain_collection_construct0x004b2340, the sibling indexed collection0x006acd34is constructed throughruntime_object_collection_construct_vtable_5cae100x00455320, the support family0x0062b244is constructed throughsupport_collection_construct_seed_counters_and_clear_large_sideband0x0040aeb0, and the live world root0x0062c120is published throughworld_runtime_construct_root_and_seed_global_0x62c1200x0044cf70before the heavier bundle load body continues through0x00449200and0x0044cfb0. The profile-side tagged header siblings are explicit too: runtime load re-entersprofile_collection_refresh_tagged_header_counts_from_bundle0x00477780, while package save later mirrors the same0x5209/0x520a/0x520btrio back out throughprofile_collection_serialize_tagged_header_counts_into_bundle0x004777e0. The same tagged symmetry is now bounded for the live company collection too: world-load refresh re-enterscompany_collection_load_tagged_header_counts_and_refresh_live_records_from_bundle0x00429af0, while the package-save path mirrors the same0x61a9/0x61aa/0x61abbracket throughcompany_collection_serialize_tagged_header_counts_and_save_live_records_into_bundle0x00429b90, whose per-company callback is currently the no-op stub0x00424000while the load-side per-company follow-on iscompany_refresh_post_load_year_clamp_and_runtime_support_fields0x004268e0. The same tagged symmetry is now bounded for the live train collection too: world-load refresh re-enterstrain_collection_load_tagged_header_counts_and_refresh_live_records_from_bundle0x004b2700, while the package-save path mirrors the same0x5209/0x520a/0x520bheader bracket and per-train record walk throughtrain_collection_serialize_tagged_header_counts_and_save_live_records_into_bundle0x004b27a0; the per-train payload seam itself is now explicit too, with route-list load throughtrain_refresh_tagged_route_list_payload_from_bundle0x004a84b0and route-list save throughtrain_serialize_tagged_route_list_payload_into_bundle0x004a7030. 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 pathshell_transition_mode(4, 0)returns cleanly, and the full old-mode teardown stack under0x5389c0now returns too, including0x5400c0, the0x53fe00 -> 0x53f860remove-node sweep over[object+0x74], and the nearby mode-2teardown helper0x00502720. The same live run now also reaches and returns fromshell_load_screen_window_construct0x004ea620and the immediate shell publish through0x00538e50. Its constructor jump table is tighter now too: mode1is not the directGame.winconstructor, but the startup-dispatch arm rooted at0x483012; mode2entersSetup.win, mode3entersVideo.win, mode4enters the plainLoadScreen.winbranch at0x4832e5, mode5entersMultiplayer.win, mode6entersCredits.win, and mode7entersCampaign.win. The important static correction is that the startup-runtime slice0x004ea710 -> 0x0053b070(0x46c40) -> 0x004336d0 -> 0x00438890belongs to mode1, not mode4. Mode4only constructs and publishes theLoadScreen.winobject through0x004ea620and0x00538e50. 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_bringupreaches the same owner at0x443b57with(0, 0)after dismissing the current shell detail panel and servicing0x4834e0(0, 0), while the saved-runtime path at0x446d7fdoes the same before immediately building the.smpbundle payloads through0x530c80/0x531150/0x531360. That makes theLoadScreen.winstartup lane the only currently grounded caller that enters0x438890with(1, 0)instead of(0, 0). The remaining runtime uncertainty is narrower now too: the plain-run logs still show the plainLoadScreen.winstate 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 expected0x46c40startup-runtime allocation. The first lower allocator probe on0x005a125dwas 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-jmpthunk 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 mode1, not mode4.mode_id = 2, and it never advanced intoready gate passed, staging, or transition. So that run did not actually exercise the0x0053b070 -> 0x004336d0 -> 0x00438890subchain at all. The next runtime pass now lowers the ready-poll defaults to1and0and adds an explicit ready-count log so the mode-4startup 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 theshell_transition_modepath again, withLoadScreen.winconstruction and publish returning cleanly. The post-publish startup subchain is no longer unresolved on the static side, though. Direct disassembly of the mode-4branch at0x0048302a..0x004830canow closes it completely: after constructingLoadScreen.win, the branch sets shell state[transition+0x08] = 4, chooses one page scalar110.0f,236.0f, or5.0f, writes that page id throughshell_load_screen_window_set_active_page0x004ea710, allocates one0x46c40-byte runtime object through0x0053b070, resets it throughworld_runtime_reset_startup_dispatch_state_bands0x004336d0, stores the result into0x006cec78, and then directly entersshell_active_mode_run_profile_startup_and_load_dispatch0x00438890as(1, 0)before publishing the active-mode object back through0x005389c0. So the static startup chain afterLoadScreen.winpublish is now explicit rather than inferred from the earlier hook traces. The remaining runtime-side question is narrower: why the earlier hook snapshots still showed[LoadScreen.win+0x78] == 0and0x006cec78 == 0immediately after transition return even though the static mode-4branch does not leave those fields that way once it reaches the startup-dispatch path. The internal selector split in0x438890is tighter now too:[0x006cec7c+0x01]is a separate seven-way startup selector, not the shell mode id. Values1and7loadTutorial_2.gmpandTutorial_1.gmp, values3/5/6collapse into the same profile-seeded file-load lane through0x445ac0([0x006cec7c]+0x11, 4, &out_success), value2is a world-root initialization lane that allocates0x0062c120and then forces selector3, and value4is the setup-side world reset or regeneration lane that rebuilds0x0062c120from0x006d14cc/0x006d14d0before later world setup continues. The write side is tighter now too:Campaign.winwrites selector6,Multiplayer.winwrites selector3on one pending-status path, and the largerSetup.windispatcher writes selectors2,3,4, and5on 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_bringupat0x00443a50no longer stops at the initial shell transition and world allocation head. The same grounded function continues through the larger post-load generation tail up to0x00444dc2, which means the laterSetting 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 through0x433130, chairman-profile materialization through0x437220, neighboring route and tracker refresh families, and the one-shot kind-8runtime-effect service through0x432f40before clearing shell-profile latch[0x006cec7c+0x97]. TheSetup.windispatcher is less opaque now too: the early0x0bc1..0x0c24family is mostly fixed submode selection above0x00502c00, except for the separate0x0bc2/0x0bc5/0x0bc6/0x0bc7shell-open quartet above0x00501f20;0x0c1fis the settings-window escape;0x0c1e/0x0c20/0x0c22are direct shell requests into0x00482150; the fixed submode buttons now have concrete lower targets such as0x0bc1/0x0bc8 -> 15,0x0bc3 -> 16,0x0bc4 -> 1,0x0c80 -> 13,0x0c1c -> 17,0x0c1d -> 2,0x0c24 -> 14,0x0c81 -> 14,0x0c82 -> 6,0x0c83 -> 10, and0x0c84 -> 12; the0x0ce6/0x0ce7/0x0d49/0x0d4a/0x0e82/0x0e83branches are bounded list or slider adjustments on staged setup fields; and the later0x0dca/0x0dcb/0x0de9/0x0df3/0x0e81/0x0f6f/0x0f70controls are the explicit selector-writing launch buttons rather than one anonymous validated-launch blob. The constructor-side callbacks are tighter too: control0x0ce8is a table-driven payload-label draw callback above0x00502030, not another launch root; that callback now clearly sits on top of the indexed string-table getter0x0053de00before handing the selected text span into the world-anchor marker queue path. Controls0x0e86and0x0e87do not select more setup roots; they update the persisted shell-state selector pairs at[0x006cec74+0x233/+0x237]and[0x006cec74+0x23b/+0x23f]through0x00502160and0x005021c0, then immediately save config through0x00484910(1). The constructor body is tighter too: it seeds the initialSetup.winstate by running0x502910,0x502550, and0x502c00(1)before the user interacts with the window, installs0x0c80..0x0c86and0x0f6f..0x0f71as homogeneous button bands, and treats0x0e88as one separate special control with retuned float fields rather than another ordinary launch root. The remaining optional constructor child0x0bd0is 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:0x53fa50is the shared resource-bind and child-list initialization helper,0x53f830is the child-control lookup-by-id helper over the intrusive list at[this+0x70],0x558130is the child-control finalizer that stamps the owner pointer and resolves localized captions before the control goes live, and0x53f9c0is the ordered child-control registration helper used by the optional0x0bd0branch and other shell dialogs. The submode selector itself is tighter now too because its button-state lane is mostly decoded:0xbc5tracks submode15,0xbc6tracks16,0xbbatracks2,0xbbbtracks3,0xbc3tracks13,0xbbcgroups3/4/5,0xbbdtracks4,0xbbetracks5,0xbbfgroups6/12/14,0xbc0tracks7,0xbc1tracks8,0xbc2tracks9,0xe75tracks10, and0xf6etracks17. 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: submode1is the strongest current landing-panel fit,2is theSingle Playerroot,7/8/9are theEditor/New Map/Load Mapfamily,15isExtras, and17isTutorial. By elimination against the separate shellCredits.winmode, the remaining top-levelSetup.winroots now most safely read as13 = Multi Playerand16 = High Scores. The file-backed side is tighter too:0x502c00now maps submodes exactly as4 -> dataset 5,9 -> 4,6 -> 8,10 -> 6,12 -> 10, and14 -> 9, so the saved-game-backed family is no longer one blurred list pane but a small set of stable dataset variants above0x4333f0/0x4336a0. The file-list builder under that pair is tighter too:0x4333f0no longer just emits unsorted0x25a-byte rows with raw names at+0x0and normalized labels at+0x12d. After the scan it now clearly re-enters0x51dc60, which is a generic adjacent-swap insertion sort over fixed records; in this setup-side caller it receivesrecord_size = 0x25aandkey_offset = 0x12d, so the resultingSetup.winrows are sorted by display label rather than by the raw filename. The file-backed header split is tighter too:0x5027b0now maps the top header-control ids as4 -> 0xd4b,9 -> 0xde8,6/12/14 -> 0xdf2, and10 -> 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: underrt3_2WIN.PK4the distinct file-backed setup art families are the sharedSetup_Loadlane and the separateSetup_Sandboxlane, which matches the selector-side evidence that mode10is the sandbox-backednewlist while mode12is itsloadsibling. Combined with the builder at0x4333f0, that shows only submodes4and10using the alternate localized-stem list-label path;6,9,12, and14keep the direct filename-normalization lane. Thert3_2WIN.PK4extraction path is grounded a bit more cleanly now too: currentpack4samples use a shared0x03ebheader, a fixed0x4a-byte directory entry stride, and a payload base at8 + entry_count * 0x4a. In the checked UI bundle the entry table is contiguous andCampaign.winextracts cleanly at directory index3with payload length0x306a. The extracted.winpayload family now has one narrow shared shape too:Campaign.win,CompanyDetail.win, andsetup.winall share the same first0x50bytes at offsets0x00,0x0c,0x10,0x14,0x34,0x38,0x40, and0x48, whileCompanyDetail.winandsetup.winalso carry an inline root.imbname immediately at0x51. Current resource scans showCampaign.winembedding thelitCamp*/Ribbon*family,CompanyDetail.winembedding mainlyCompanyDetail.imb,GameWindow.imb, andPortrait.imb, andsetup.winembedding the broaderSetup_Background/Buttons/New_Game/Load/Sandboxart families. The control records between those strings are still undecoded, but the resource-record shell itself is tighter now: all checked.winsamples use the same three-word prelude prefix0x0bb8, 0x0, 0x0bb9, and the fourth prelude word matchesresource_name_len + 1. The next word after the terminating NUL then behaves like a per-record selector lane. Insetup.winthe dominantSetup_Buttons.imbfamily alternates between0x00040000and the incrementing0x00010c1c..0x00010c86series with dominant inter-record strides0xb7/0xdb; inCampaign.winthelitCamp*/Ribbon*family carries the incrementing0x0004c372..0x0004c38eselector block with dominant0x158/0x159and0xb2/0xb3strides. That campaign lane is now directly aligned to the executable-side control ids too: the low 16 bits oflitCamp1..16map exactly to0xc372..0xc381, and the low 16 bits ofRibbon1..16map exactly to0xc382..0xc391, matching theCampaign.winprogress and selector control bases already grounded fromRT3.exe. The fuller selector export now tightens the auxiliary families too:litArrows.imbcovers0xc36c..0xc371exactly andlitExits.imbcovers0xc397..0xc39aexactly, 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 sameCampaign.winrecords under0xc368,0xc369,0xc36a, and0xc36b, 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.imbselector records for0xc393..0xc396or0xc39b, which makes those message-side page-write controls look more like structural buttons than art-backed repeated resource records. The grouped3/4/5family is narrower now too:0x0ce5is no longer part of it, because that control writes selector3and then selects submode9as theLoad Mapsibling. The nearby0x0dcbbranch instead conditionally selects submode5or3, which keeps3as the strongest currentNew Game/Optionscompanion and5as the strongest currentSandboxcompanion. The file-backed single-player side is tighter in the same way now: modes4and10are 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. Mode10is the stronger one of the pair because neighboring validated launch control0x0e81both routes into selector5and sets sandbox byte[0x006cec7c+0x82] = 1, which makes it the strongest current fit for the setup-localNew Sandboxlist. The distinctSetup_Sandboxart family inrt3_2WIN.PK4now reinforces that same split one step further, which makes mode12the strongest closed fit for the pairedLoad Sandboxlane; mode4is therefore the strongest remaining non-sandbox peer in that same pair and now most safely reads as the setup-localNew Scenario-style chooser. Modes6,12, and14now tighten one step further as the three selector-3direct-filename setup-localloadsiblings because they stay on the direct filename-normalization lane, share the same0xdf2header family, and clear the same presence-style latch[0x006cec7c+0x97]; mode14is the strongest current landing panel for that cluster because0x0c24jumps to it directly while0x0c82and0x0c84only reach the sibling modes6and12from inside the same load family. Current control-pairing and setup-art evidence now make12 = Load Sandboxthe strongest closed per-submode assignment. The remaining non-sandbox pair is closed now too: the deeper bundle filter at0x433260distinguishes dataset9from dataset8by one extra nonzero payload-flag family, and the editor-side metadata path now grounds[0x006cec78+0x66de]as the directCampaign Scenariocheckbox bit becauseeditorDetail.winties control0x5b6eto localized ids3160/3161. That makes dataset9the campaign-designated load family and dataset8the ordinary scenario load family, so14 = Load Campaignand6 = Load Scenarionow read as grounded rather than residual.0x502910is 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 formats0xcf3/0xcf4/0xcf5/0xd4f, mirrors option byte[0x006cec7c+0x7d]into0x0ce9..0x0ced, rebuilds row host0x0ce8from payload bytes[+0x31b/+0x31c], and mirrors live row markers into[0x006cec7c+0x87]. That makes mode3just 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:0x502220does not just republish labels and the preview surface. It first re-entersshell_setup_load_selected_profile_bundle_into_payload_record0x442400, which clears one full0x100f2-byte setup payload record, builds a rooted path from the staged profile stem, opens the selected bundle through0x530c80, and then reads either the ordinary saved-profile chunk family or the map-style chunk family through0x531150/0x531360depending on the selected extension shape. Only after that does0x502220copy payload fields+0x14/+0x3b2/+0x3ba/+0x20into the staged runtime profile through0x47be50, which in turn normalizes the payload category bytes at[payload+0x31a + row*9]and the local marker-slot bytes at[payload+0x2c9..]through0x47bc80. The copied-field consumer split is tighter now too: payload+0x14becomes staged profile[0x006cec7c+0x77], which is the visible setup scalar later formatted into controls0x0e84and0x0d4fand adjusted by the0x0d49/0x0d4apair; payload+0x3b2becomes[0x006cec7c+0x79], the live-row threshold that the payload-row draw callback uses to choose style slot0x18versus0x19; and payload+0x3babecomes[0x006cec7c+0x7b], the current scroll or row-index lane adjusted by the0x0ce6/0x0ce7pair. 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 families0x0004/0x2ee0/0x2ee1into one large0x100f2-byte payload record, and the fixed0x6a70..0x73c0candidate 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 carry the candidate table conservatively as a lower setup-side candidate-table slab inside the broader setup payload family, even though the current named setup-side consumers still land only on earlier payload offsets. The newer fixed-offset compare pass tightens that lower setup slice too: across the checked map/save pairsAlternate USA.gmp -> Autosave.gms,Southern Pacific.gmp -> p.gms, andSpanish Mainline.gmp -> g.gms, the known setup payload lanes+0x14and+0x3b2are preserved map-to-save on the same scenario-family split as the later candidate-table headers (0x0771/0x0001,0x0746/0x0006,0x0754/0x0001), while+0x3aestays fixed at0x0186and+0x3bastays fixed at1across all six files. By contrast,+0x20does not survive as one shared source value (0xd3 -> 0xb4,0x6f -> 0x65,0xe3 -> 0x78across those same pairs). So the current best read is that the setup payload mixes preserved scenario metadata and later save-variant state well before the0x6a70candidate 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 around0x422320..0x423d30, whose current grounded helpers now include0x422320,0x4228b0,0x422900,0x422a70,0x422be0,0x422ee0,0x4234e0,0x4235c0, andworld_region_refresh_cached_category_totals_and_weight_slots0x423d30rather than one hidden setup-only panel. The leading region helper is no longer unnamed either:0x422320is now bounded as the recurring cached-structure-scalar normalization pass that writes[region+0x2e2/+0x2e6/+0x2ea/+0x2ee], while0x422a70is the shared placement-validation and commit gate beneath both the per-region worker and one second world-side placement loop. The neighboring0x4234e0accessor 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:0x502550is not another hidden submode owner. It republishes the staged path tail in0xe7f, the scalar summary in0xe84, the two persisted selector lists in0xe86/0xe87, and the config toggles in0xe88/0xe89/0xe8a. The remaining top-level gap is cleaner now too: submode16still 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 the0x0bc3 -> 16top-level button whose visual-state lane is surfaced through control0xbc6, and the strongest residual fit isHigh ScoresbecauseCreditsalready lives in separate shell mode6. The validated launch lane is tighter now too: it no longer just writes selector3or5as one undifferentiated blob, and it no longer includes0x0ce5or0x0dcb.0x0ce5is theLoad Mapselector because it writes selector3and then selects submode9, while0x0dcbis the later conditional5/3companion-selector sibling rather than a file launch. The actual validated staged-profile lane is now bounded more narrowly:0x0cf6and0x0e81are the selector-5siblings, while the neighboring selector-3validated lane is at least shared by0x0de9and0x0df3; the shared bridge at0x4425d0then forces[0x006cec7c+0xc5] = 1, mirrors payload bytes into[profile+0xc4],[profile+0x7d], and[profile+0xc6..+0xd5], and only then issues shell request0x0cc. The file-side staging bytes in that bridge are now tighter too: across the checkedAlternate USA,Southern Pacific, andSpanish Mainlinemap/save pairs, payload+0x33stays0, but payload+0x22and token block+0x23..+0x32do not preserve the earlier map-to-save pairing seen at+0x14/+0x3b2. Instead they split by the finer file family, with examplesAlternate USA.gmp = 0x53 / 0131115401...versusAutosave.gms = 0xae / 01439aae01...,Southern Pacific.gmp = 0xeb / 00edeeeb...versusp.gms = 0x21 / 0100892101..., andSpanish Mainline.gmp = 0x5b / 0044f05b...versusg.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.gmcsave helper0x00517c70;[profile+0x7d]is the same compact option byte mirrored back into theSetup.winoption controls0x0ce9..0x0ced; and the campaign-side selector block is no longer only a one-byte anchor. DirectRT3.exedisassembly of the campaign-side dispatcher at0x004b89c0now shows the exact mirror shape: when the local campaign-page selector[window+0x78] <= 4, the helper writes one highlighted progress control0x0c372 + [profile+0xc4]and then mirrors the full sixteen-byte band[profile+0xc6..+0xd5]into controls0x0c382..0x0c391through repeated0x540120calls. The same body also treats[profile+0xc4]as an index into the fixed sixteen-entry scenario-name table at0x00621cf0, whose observed entries includeGo 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, andCalifornia Island. On the launch-side branch the same helper writes startup selector6, copies the resolved campaign filename into[profile+0x11], forces[profile+0xc5] = 1, and then issues shell request0x0cc. The lower refresh tail at0x004b8d49..0x004b8d69also shows the observed page-band split over the same progress byte: values< 5pair with campaign page1, values5..9with page2, values10..12with page3, and values>= 13with page4. 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 byCampaign.win. The neighboring profile helpers are tighter now too:0x0047bbf0is the broad default reset for the staged0x108-byte runtime-profile record, clearing the whole record and then reseeding the visible setup and campaign anchors[profile+0x77],[profile+0x79],[profile+0x7d], the random-like dword[profile+0x83], the first setup row-marker byte[profile+0x87], and the file-backed launch or rehydrate latch[profile+0x97];0x00502c00is now tighter on the same slab because its file-backed lane copies the selected row's primary and secondary0x32-byte string bands into[profile+0x11]and[profile+0x44]while arming presence byte[profile+0x10]; and0x0047bc50is the compact scan helper over[profile+0xc6..+0xd5]that returns the first selector byte below2, which keeps that band tied to staged campaign progress or unlock state rather than to the earlier setup-panel payload fields. The message-dispatch side is tighter now too. The local classifier at0x004b91d8routes the control range0x0c352..0x0c39bthrough five concrete case classes:0x0c352..0x0c361enter the shared selector or launch branch,0x0c362..0x0c367force local page1,0x0c368..0x0c392force local page2,0x0c393..0x0c396force local page0, and0x0c39balone forces local page3. That matches the constructor and refresh shape: the sixteen scenario selector controls live at0x0c352..0x0c361, the four page-strip controls live at0x0c368..0x0c36b, the six-arrow auxiliary strip lives at0x0c36c..0x0c371, the progress band lives at0x0c372..0x0c381, the ribbon or selector band lives at0x0c382..0x0c391, the string or voice target lane lives at0x0c392, the four exit controls live at0x0c397..0x0c39a, and0x0c39bremains the one-off special action control that spawns or dismisses the campaign-side companion object. TheCampaign.winblob now exposes that structural split directly too: alongside the art-backed0x0004c3xxrecords it carries anonymous zero-name records with the same0x0bb8 / 0 / 0x0bb9prelude but selector words in the0x0010c3xxfamily. Current local extraction shows exactly0x0010c352..0x0010c361,0x0010c362..0x0010c367,0x0010c393..0x0010c396, and one0x0010c39brecord, which is the same non-.imbband 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:0xc368for0xc352..0xc356,0xc362,0xc393, and0xc39b;0xc369for0xc357..0xc35b,0xc363, and0xc394;0xc36afor0xc35c..0xc35e,0xc365..0xc366, and0xc395; and0xc36bfor0xc367,0xc35f..0xc361, and0xc396. One final anonymous record at0x0002c392has no page bucket at all, which fits the already-grounded read of0xc392as 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 words0xd3000000and0xd2000007at relative+0x98/+0x9c, while the lone0xc392record carries0x00000000/0x00000000there. So0xc392is 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..0xc361partition exactly as5 + 5 + 3 + 3across page buckets0xc368..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..0xc361each sit immediately after oneRibbonN.imbrecord and before the nextlitCamprecord, 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..0xc367sit inside the locallitArrows.imbclusters,0xc393..0xc396sit inside thelitExits.imbclusters, and0xc39bsits 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 currentCampaign.windump the ordinary anonymous structural records all span0x0a7bytes, while the named art-backed records cluster at0x0b1,0x0b2, and0x0b3. The only two visible outliers are the leading0x0080c351record at0x0041with span0x0a3, and the trailing0x0002c392record at0x2fb9with span0x0b1. That reinforces the current read that0xc351and0xc392are 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 checkedAlternate USA,Southern Pacific, andSpanish Mainline.gmp/.gmsfiles are decoded with that same campaign-side interpretation, payload byte+0x22is always outside the known campaign progress range0..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..+0x32is 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, chieflyGo West!,Germantown,Central Pacific,Texas Tea, andWar Effort, with scenario-family-specific byte values rather than a simple0/1unlock 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/.gmscontent is already in campaign-screen form. Only0x0e81also sets[0x006cec7c+0x82] = 1, which is currently the strongest sandbox-side anchor beneath the later.gmxload family. That launch band is slightly tighter now too:0x0dcais the grayscale-map picker branch above theTGA Files (*.tga)/.\Data\GrayscaleMapshelper at0x004eb0b0, not another ordinary save-file validator. That launch band is tighter in a second way too:0x0ddfis not a lobby branch after all, but the separate windowed-mode-gated grayscale-heightmap generation path. It reopens theTGA Files (*.tga)/.\Data\GrayscaleMapspicker through0x0042a970, validates the chosen image through0x005411c0, and only then writes startup selector2. The fixed- button side is tighter too: submode15now aligns with theExtrasfamily because it sits above the Readme/Weblinks shell-open quartet and the return-to-extras sibling, while submode17now aligns with the tutorial chooser because it is the only branch that later exposes startup selectors1and7, which RT3 uses forTutorial_2.gmpandTutorial_1.gmp. The map-root family is tighter too: submodes7/8/9are the only setup branch that flips the file root intomaps\\*.gm*, with mode8specifically the grayscale-heightmap picker and mode9the file-backed map-list sibling. Submode13is slightly tighter now too: current local evidence shows that it stays outside both the dedicated file-backed pane and the mode-3option-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 at0x4333f0formats eithersaved games\\*.smpormaps\\*.gm*from the shell-state fields at[0x006cec74+0x68/+0x6c], with the separatedata\\tutorialroot only appearing on the tutorial-side[shell+0x6c] == 2branch. That means theSetup.winsubmode families are no longer one generic file pane: the ordinary setup-backed.smpfamily is broader than the narrower file-list pane, because modes3/4/5/6/10/12/14stay on the ordinary saved-game side while only4/6/9/10/12/14re-enter the dedicated file-list panel at0x5027b0; themapsbranch 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, and0x00444dd0, plus objdump string and mode-table evidence for.gmp,.gmx,.gmc,.gms,.gmt,.smp,Quicksave, the0x004dd010mode table at0x005f3d58, the auxiliary-owner presence check at0x00434050, and the.gmthandoff through0x00469d30, together with localized string evidence from ids3018and3898. - Direct shell stubs above that coordinator are tighter now too:
0x004408b0is the ordinarySave gamewrapper and forwards the pure zero-flag triplet intoshell_map_file_world_bundle_coordinator;0x004408d0is the siblingQuick savewrapper, forwarding flag triplet(0, 1, 0). RT3.lng closes the neighboringshell_map_file_entry_coordinatorpair in the same way:0x00441ac0isLoad gameand0x00441af0isQuick load, with the same(0, 0, 0)versus(0, 1, 0)split above0x00445ac0. - Current Boundary: bit
0x1on both broad coordinators now grounds the Quicksave name seed and the former thirdfileopt.winflag has been ruled out as a file-flow question because it just opensSettingsWindow.win. The extension family is now carried conservatively as.gmpfor the editor-map pair,.gmsfor the standalone scenario family,.gmcfor the campaign-scenario family,.gmxfor the sandbox family, and.gmtfor the auxiliary preview-surface branch rather than another gameplay save family. The higher-value handoff boundary is also closed at the current evidence level: after this bring-up, long-lived simulation cadence still rendezvous with the same shell-owned frame path rather than surfacing a detached gameplay-only outer loop.