Skip to content

Symbol map — anchor renaming#

High-confidence renames from Ghidra FUN_* / DAT_* / LAB_* to human-readable names. Each entry lists evidence used to assign the name.

Apply via tools/ghidra/apply_anchor_renames.py. Workflow: RENAME_WORKFLOW.md.

Progress#

Metric Count Notes
Documented renames ~2144 Rows in this table + passes 29–65
FUN_* still referenced in active code 0 After pass 48 (CRT tail complete)
Renamed function definitions (lotr2_* / crt_*) ~2100+ Includes pass 50 net handler sweep
Provenance comments (// was FUN_ / // was DAT_) ~1502+ Above renamed definitions
DAT_* renamed to lotr2_* ~333 Pass 65 adds 95 save-field globals; ~60 remain lotr2_unk_* provisional
Pass status Pass 65 (save-field DAT globals — all 203 save blocks) 95 named globals; ~60 provisional lotr2_unk_*

Last batch: pass 65 — 95 symbols documented in save-field DAT pass; see pass 65 section. Prior batch: pass 64 — 5 symbols via tools/ghidra/dat_renames_pass64.py: Game — troop-yield resource pools (kinds 9 / 0xb / 0xd / 0xe) updated in lotr2_game_apply_resource_delta and lotr2_game_finalize_army_turn; faction upkeep total summed for province overview UI. GoG mappings in same pass file. Struct: docs/structs/lotr2_player_record.md. Prior batch: pass 63 — 8 symbols via tools/ghidra/dat_renames_pass63.py: Game — upkeep tax accumulators (+0xf0/+0xf4), treasury pay/recv ledger pairs updated in lotr2_game_apply_resource_delta, build-reserve snapshots for diplomacy affordability (lotr2_game_diplomacy_max_affordable). GoG aliases in same pass file. Struct: docs/structs/lotr2_player_record.md. Prior batch: pass 62 — 13 symbols via tools/ghidra/dat_renames_pass62.py: Combat — per-player fog/reveal mask OR'd into lotr2_combat_figure_visibility_flags (+0x0a in figure stride 0x1b0). Game — treasury, upkeep army strength, build reserves (slots 0/1/3), troop stock array + total, crown tally, upkeep warning stage, battle-message variant index. Struct: docs/structs/lotr2_player_record.md. Prior batch: pass 61 — 8 symbols via tools/ghidra/dat_renames_pass61.py: Game — per-player AI turn scratch (+0xe1..+0xe9 within 0x160 slot): primary/secondary provinces, attack army slot, taunt counter, war-target override, alliance attempt counter, sole-survivor flag. Struct: docs/structs/lotr2_player_record.md. Prior batch: pass 60 — 9 symbols via tools/ghidra/dat_renames_pass60.py: Game — per-foe diplomacy row (stride 0x10 within player 0x160 slot from 0x55ae24): attitude, alliance, war escalation, tribute peak, truce/contact. Prior batch: pass 59 — 12 symbols via tools/ghidra/dat_renames_pass59.py: Game — player record AI/diplomacy scratch (stride 0x160 from 0x55adbc): attack pending/wait, war target, staging army, build rotation, alliance partner, troop-buy budgets. Struct: docs/structs/lotr2_player_record.md. Prior batch: pass 58 — 13 symbols via tools/ghidra/dat_renames_pass58.py: Game — player record Great Noble / aggregate stats (stride 0x160 from 0x55adb0): province gold, county/army/troop/castle counts, score, rank tier, county ratio. Struct: docs/structs/lotr2_player_record.md. Prior batch: pass 57 — 7 symbols via tools/ghidra/dat_renames_pass57.py: Game — player record identity bytes (stride 0x160 from 0x55ada4): active, eliminated, culture row, faction/text colors, avg happiness aggregate. Struct: docs/structs/lotr2_player_record.md. Prior batch: pass 55 — 11 symbols via tools/ghidra/dat_renames_pass55.py: Net roster — opcode 3 player_ids[5], player_names[5][0x14], and slot_to_player[6] serialized by lotr2_net_pack_player_roster_sync. Struct update: docs/structs/lotr2_net_msg_roster.md. Prior batch: pass 54 — 15 symbols via tools/ghidra/dat_renames_pass53.py: Combat / game / UI — group table + alloc/cur/focus indices, great-noble stat column, difficulty preset + culture count, hover poll timestamp, pointer dirty flag, tooltip blit coords. Struct updates: docs/structs/lotr2_battle_group.md, docs/structs/lotr2_game_state.md. Prior batch: pass 52 — 17 symbols via tools/ghidra/dat_renames_pass52.py: Game / net / UI — AI sim turn phase + player-step array, army/build tables, UI text scratch + modal flag, join/roster payload globals, combat tile scan, asset scratch pointer, toolbar context slot. Struct updates: docs/structs/lotr2_game_state.md, lotr2_net_msg_join.md. Prior batch: pass 51 — 15 symbols via tools/ghidra/game_renames_pass51.py: Game subsystem — turn-action semantic names (enter_mode_0x* → dialog names; mp_send_0x1230x127 → toolbar context-panel slots) and Tier-1 state globals (lotr2_game_local_player_slot, lotr2_game_active_view, mouse coords, map tile grid, province scan index). Struct: docs/structs/lotr2_game_state.md. Prior batch: pass 50 — 133 symbols via tools/ghidra/net_renames_pass50.py: Net subsystem — final opcode placeholder sweep (lotr2_net_*_opcode_XX → semantic pack/unpack names). Evidence: lotr2_net_send_message caller map, handler payload targets, deferred-queue sub-action ids. Prior batch: pass 49 — 41 symbols via tools/ghidra/net_renames_pass49.py and tools/ghidra/game_renames_pass49.py. Prior batch: pass 48 — 37 symbols via tools/ghidra/crt_renames_pass48.py, tools/ghidra/ui_renames_pass48.py, and tools/ghidra/game_action_noop_renames_pass48.py. Prior batch: pass 47 — 35 symbols via gfx text advance + tile24 blit + VRAM/widget rect helpers; glyph/blit origin globals; turn-phase ack flags + semantic turn-action handler names; lotr2_map_province_cell, lotr2_game_map_entity_draw_token; deferred noop stubs. Struct doc: docs/structs/lotr2_game_state.md. Prior batch: pass 46 — 19 symbols via tools/ghidra/game_renames_pass46.py: text-input load/save slot I/O, clipped sprite blit, campaign map column row passes (interior/bridge/clip), entity stamp prep + PL8 dispatch, stack-icon blit, four lotr2_gfx_stamp_map_entity_* row helpers @ 0x45d4–0x45ea, empty redraw stubs. Prior batch: pass 45 — 17 symbols via tools/ghidra/combat_renames_pass45.py: battle player compare rows, siege field-battle outcome / defender-routed panels, battle HUD init + resource counters + army roster, paused overlay, MP debug overlays, intro-chapter dialog (mode 0x44). Prior batch: pass 44 — 24 symbols via tools/ghidra/game_renames_pass44.py: AI tax budget helpers, province development tick (004592850045956c), new-campaign player init (00459709), allocation slider table (00459ab10045a016), minimap overlay color refresh, gfx dirty-tile dup/stub hooks. Prior batch: pass 43 — 38 symbols via tools/ghidra/combat_renames_pass43.py: battle grid init (004d7020/004d7107), main frame tick (004d49a0), viewport orchestrator (004d7142), 16px/32px dirty-tile passes, figure paint list + Y-sort, per-type figure blit, projectile chain, MP frame gate. Prior batch: pass 42 — 49 symbols via tools/ghidra/crt_renames_pass42.py: MSVC 6.0 debug CRT — crt_free/crt_dbgheap_free (99+30 refs), optimized crt_strlen/crt_strcpy/crt_strcat, Win32 heap, timezone, fd-table lowio, CrtDbgReport worker. Prior batch: pass 41 — 44 symbols via tools/ghidra/gfx_stamp_renames_pass41.py: isometric map-cell fill (lotr2_map_draw_cell_tile rotation×edge dispatch), map-sprite row blit helpers, PL8 diagonal stamp loops. Prior batch: pass 40 — 39 symbols via tools/ghidra/map_video_renames_pass40.py: map army spawn/pathfind, 0x81×0x41 cell draw/stamp, viewport hit-test/rotation, Smacker open/decode/teardown (DirectPlayCreate4/Enumerate3 are Smacker SDK aliases — not DirectPlay networking). Prior batch: pass 39 — 22 symbols via tools/ghidra/game_renames_pass39.py: wizard step renderer cluster (0x004260000x00427fff) — asset load, step dispatcher, per-step panels (1–8), MP player list, siege assault prep (mode 0x1d). Prior batch: pass 38 — 56 symbols via tools/ghidra/game_renames_pass38.py: wizard / turn-action cluster (0x0043b0000x0043dfff) — turn-action table no-op tail, lobby/wizard helpers, replay speed setters, build-queue slot ops, diplomacy text-input sub-modes (screen mode 0x1a). Prior batch: pass 37 — 37 symbols via tools/ghidra/game_renames_pass37.py: castle-interior / gateway UI cluster (0x0041f0000x00425fff) — armoury stat rows and weapon panels, province overview (mode 0x17), post-siege screen (mode 0x11), siege battle prep HUD, diplomacy minimap, province event popups, gateway/new-game screen. Prior batch: pass 36 — 109 symbols via tools/ghidra/game_renames_pass36.py: castle/build/recruit cluster (0x004c00000x004cffff) — build queue tick, province placement, recruit spawn, army merge/march, siege assault resolution, upkeep/flag tables, castles.dat I/O, battle SFX cues, castle-view backbuf blit. Prior batch: pass 35 — 146 symbols via tools/ghidra/game_renames_pass35.py: campaign UI / sync cluster (0x0043e0000x0044ffff) — army turn finalize, post-battle return, mode-5/minimap hit-tests, tax slider, battle prep/recruit, battle scroll/figure pick, MP send gates, net remote-apply handlers. Prior batch: pass 34 — 97 symbols via tools/ghidra/game_renames_pass34.py: turn-phase dispatcher (lotr2_game_ai_turn_phase), per-player 14-step AI loop (lotr2_game_ai_player_step), build/economy templates, diplomacy queue, army pathfinding/orders, battle/conquest entry. Prior batch: pass 33 — 43 symbols via tools/ghidra/game_renames_pass33.py: text-input cursor/edit helpers, frame-counter tick, LFSR RNG, distance helpers, campaign map entity draw passes, castle overview panel rows, mode-5 panel setup. Prior batch: pass 32 — 66 symbols via tools/ghidra/asset_ui_renames_pass32.py: asset probe/write/ini-byte, status.txt + diverged dump, palette fade/dim/remap, Win32 pointer poll + cursor themes + message-pump hooks. Pass 31 — 19 symbols via tools/ghidra/audio_renames_pass31.py, io_renames_pass31.py, net_dlg_renames_pass31.py: preloaded WAV bank play/stop/release, CRT file-length/chsize/drive set, DirectPlay dialog HWND globals and EnumSessions/Enumerate LAB aliases. Pass 30 renamed 60 eng/map/io symbols; pass 29 renamed 219 game-logic symbols; pass 28 renamed net sync + combat full sweep.


Pass 1 — subsystem anchors#

Old symbol Address New symbol Evidence
FUN_0041680b 0x41680b lotr2_winmain Called from entry() after CRT init; registers window, runs message loop (PeekMessageA / GetMessageA / DispatchMessageA)
FUN_004cc954 0x4cc954 lotr2_ui_create_main_window RegisterClassA (WinLords2Class), CreateWindowExA (Lords2), LoadCursorA
LAB_0040209a 0x40209a lotr2_ui_wndproc Assigned to WNDCLASSA.lpfnWndProc
FUN_004cd0a4 0x4cd0a4 lotr2_ui_wndproc_impl Full window procedure; ends with DefWindowProcA
DAT_0050773c 0x50773c lotr2_ui_hwnd_main Stores CreateWindowExA return value
FUN_004cd008 0x4cd008 lotr2_gfx_init_display Post-window init; loads base01.256, sets display mode flag
FUN_00436c80 0x436c80 lotr2_gfx_init_directdraw DirectDrawCreate, cooperative level, palette
FUN_004ccf34 0x4ccf34 lotr2_gfx_init_complete Calls lotr2_gfx_init_directdraw, surface setup
FUN_004ccfb3 0x4ccfb3 lotr2_gfx_release_ddraw Releases DirectDraw interface via vtable
DAT_00507a6c 0x507a6c lotr2_gfx_lpdd IDirectDraw* passed to DirectDrawCreate
FUN_0042fc90 0x42fc90 lotr2_audio_init_directsound DirectSoundCreate, primary buffer setup
DAT_004ef810 0x4ef810 lotr2_audio_lpds IDirectSound* from DirectSoundCreate
DAT_00531028 0x531028 lotr2_audio_dsound_hr HRESULT scratch for DirectSound vtable calls
FUN_004d4110 0x4d4110 lotr2_audio_load_wav_mmio mmioOpenA, RIFF/WAVE parse, mmioRead
FUN_004d43ea 0x4d43ea lotr2_audio_parse_wav_chunk Parses fmt chunk after lotr2_audio_load_wav_mmio
FUN_004d4629 0x4d4629 lotr2_audio_free_wav_buffer Frees WAV sample buffer
FUN_004306b4 0x4306b4 lotr2_audio_create_buffer_from_wav Creates DirectSound buffer from loaded WAV
FUN_00430d12 0x430d12 lotr2_audio_start_stream_timer timeSetEvent for streaming playback
FUN_00430e91 0x430e91 lotr2_audio_stop_stream_timer timeKillEvent / buffer unlock
LAB_00401cdf 0x401cdf lotr2_audio_stream_timer_proc timeSetEvent callback address
FUN_004e7110 0x4e7110 lotr2_io_create_file CreateFileA, GetFileType
FUN_004e70c0 0x4e70c0 lotr2_io_open Thin wrapper around lotr2_io_create_file
FUN_004ca01c 0x4ca01c lotr2_asset_read_file Opens via lotr2_io_open, __read into buffer; used for .pl8/.256/.dat
FUN_00435d1b 0x435d1b lotr2_video_play_smk Smacker playback; callers pass *.smk string tables
FUN_00436460 0x436460 lotr2_video_start_cutscene Dispatches intro.smk / imptitle.smk via _strcmp
FUN_004de770 0x4de770 crt_CrtDbgReport MSVC debug report; called from CRT assert paths
FUN_004db6e0 0x4db6e0 crt_dbgheap_alloc Debug heap alloc; __FILE__ = dbgheap.c
FUN_004e2a40 0x4e2a40 crt_output_format Printf core; __FILE__ = output.c
Ordinal_1 0x4db1e4 DirectPlayCreate DPLAYX.DLL ordinal-1 import stub; called as DirectPlayCreate(guid,&obj,0)
Ordinal_2 0x4db1de DirectPlayEnumerate DPLAYX.DLL ordinal-2 import stub; enumerates service providers
DAT_004ff400 0x4ff400 lotr2_net_dplay3 IDirectPlay3*; vtable Send/Receive/Open/CreatePlayer/etc.
DAT_004ff408 0x4ff408 lotr2_net_local_player_id Local player DPID from CreatePlayer
DAT_004eb0d8 0x4eb0d8 lotr2_net_iid_dplay3 IID_IDirectPlay3 GUID for QueryInterface
PTR_DAT_004ff404 0x4ff404 lotr2_net_player_data Buffer passed to SetPlayerData
DAT_004ff410 0x4ff410 lotr2_net_session_preselected EnumSessions preselected-entry flag
DAT_0055a370 0x55a370 lotr2_net_session_active Multiplayer-active gate
DAT_0055a854 0x55a854 lotr2_net_handshake_done Join handshake complete flag
DAT_005636e0 0x5636e0 lotr2_net_is_host Host vs client role (set on DPSYS_HOST)
DAT_0052a578 0x52a578 lotr2_net_send_slot Rolling send-slot index (1..0x27)
FUN_004d243e 0x4d243e lotr2_net_start_session Session entry + join handshake wait
FUN_004d266d 0x4d266d lotr2_net_setup_session InitializeConnection / Open / CreatePlayer
FUN_004d2d1f 0x4d2d1f lotr2_net_create_dplay3 DirectPlayCreate + QI IDirectPlay3
FUN_004d23d0 0x4d23d0 lotr2_net_shutdown Close + Release IDirectPlay3
FUN_004d25c6 0x4d25c6 lotr2_net_leave_session DestroyPlayer + shutdown
FUN_004d260d 0x4d260d lotr2_net_set_player_data SetPlayerData (vtable +0x7c)
FUN_004d2a1e 0x4d2a1e lotr2_net_show_select_sp_dialog Service-provider picker (dialog 0x81)
FUN_004d2ac0 0x4d2ac0 lotr2_net_dlg_select_sp SP dialog proc; DirectPlayEnumerate
FUN_004d2e2e 0x4d2e2e lotr2_net_enum_sp_callback DirectPlayEnumerate callback (@0x403053)
FUN_004d2a48 0x4d2a48 lotr2_net_show_host_or_join_dialog Host/Join chooser (dialog 0x6c)
FUN_004d2ea4 0x4d2ea4 lotr2_net_dlg_host_or_join Host/Join dialog proc
FUN_004d2a99 0x4d2a99 lotr2_net_show_session_name_dialog Host session-name dialog (0x74)
FUN_004d2fa2 0x4d2fa2 lotr2_net_dlg_session_name Session-name dialog proc
FUN_004d2a6f 0x4d2a6f lotr2_net_show_browse_sessions_dialog Session browser (dialog 0x82)
FUN_004d3120 0x4d3120 lotr2_net_dlg_browse_sessions EnumSessions + Open(join) dialog proc
FUN_004d2d7b 0x4d2d7b lotr2_net_enum_sessions_callback EnumSessions callback (@0x40209f)
FUN_004d36f0 0x4d36f0 lotr2_net_poll_messages Receive pump; system vs app routing
FUN_004d39d5 0x4d39d5 lotr2_net_dp_send IDirectPlay3::Send wrapper
FUN_00448641 0x448641 lotr2_net_send_message Pack + checksum + reliable triple-send
FUN_00448362 0x448362 lotr2_net_dispatch_app_message Validate + dedupe + dispatch app msg
FUN_004480ef 0x4480ef lotr2_net_handle_system_message DPSYS_* handler
FUN_004480b5 0x4480b5 lotr2_net_on_fatal_error Net error -> shutdown + quit
FUN_004482c2 0x4482c2 lotr2_net_player_id_to_slot DPID -> player slot lookup
FUN_00448319 0x448319 lotr2_net_store_player_ids Copy player DPIDs into slot table
FUN_00448832 0x448832 lotr2_net_reset_send_state Reset send slots / counters pre-play
FUN_00448ad4 0x448ad4 lotr2_net_set_player_ready_flags Per-player ready flags
FUN_00448c6c 0x448c6c lotr2_net_checksum 8-bit additive payload checksum
FUN_00448dee 0x448dee lotr2_net_payload_write Append bytes to send payload
FUN_00448e2a 0x448e2a lotr2_net_payload_read Read bytes from receive payload
FUN_00449e77 0x449e77 lotr2_net_pack_local_id Pack local DPID + name
FUN_00449fcc 0x449fcc lotr2_net_pack_join_data Pack join handshake data
FUN_0044a03b 0x44a03b lotr2_net_on_join_handshake Apply join handshake; set handshake_done

Pass 2 — anchor subsystem callees#

Old symbol Address New symbol Evidence
FUN_00431b10 0x431b10 lotr2_audio_play_wav Gates on lotr2_audio_lpds; loads .wav via lotr2_audio_load_wav_file; creates/plays secondary buffer
FUN_00431e1b 0x431e1b lotr2_audio_buffer_is_playing IDirectSoundBuffer::GetStatus (vtable +0x24); returns 1 when status == 1
FUN_00431e99 0x431e99 lotr2_audio_release_secondary_buffer Stop + Release on lotr2_audio_dsb_playback (vtable +0x48, +8)
FUN_00431ef2 0x431ef2 lotr2_audio_hresult_to_code Maps DirectSound DSERR_* HRESULT constants to small integer codes
FUN_0043052d 0x43052d lotr2_audio_start_stream_from_name Copies path to stream slot; calls create-buffer + start-stream-timer
FUN_004d467f 0x4d467f lotr2_audio_load_wav_file Orchestrates mmio open, fmt parse, chunk read into GlobalAlloc buffer
FUN_004d4482 0x4d4482 lotr2_audio_mmio_read_chunk mmioAdvance + memcpy loop for WAVE data chunk
DAT_0053102c 0x53102c lotr2_audio_dsb_playback IDirectSoundBuffer* for one-shot WAV playback
FUN_00448b3f 0x448b3f lotr2_net_clear_send_slot_table Zeros 6×10 send-slot table; called from lotr2_net_reset_send_state
FUN_00448b9a 0x448b9a lotr2_net_clear_recv_dedupe_table Zeros 7×0x28 receive dedupe table
FUN_00448bfa 0x448bfa lotr2_net_clear_msg_history_table Zeros per-player message history rows
FUN_00416aea 0x416aea lotr2_game_load_config Reads l2.ini / _sierra.ini via lotr2_asset_read_file; sets display/audio globals
FUN_0041671b 0x41671b lotr2_game_idle_tick Idle handler when message queue empty; DD flip path + game tick dispatch

Pass 3 — combat / siege#

Old symbol Address New symbol Evidence
thunk_FUN_00492cb1 0x00492cb1 lotr2_combat_update_attack_damage Reads 0x004f4c18 by unit type + formation tier into figure attack_damage
thunk_FUN_004a48c6 0x004a48c6 lotr2_combat_apply_melee_hit Adds attacker attack_damage to defender damage_acc; 100-point casualty rule
thunk_FUN_00496fa3 0x00496fa3 lotr2_combat_update_move_step Infantry movement step bases (unit_type < 7)
thunk_FUN_004994ed 0x004994ed lotr2_combat_siege_update_sprite_a Siege unit sprite row update (types 7–10)
thunk_FUN_004996b8 0x004996b8 lotr2_combat_siege_update_sprite_b Siege sprite variant (knight/oil paths)
FUN_00493754FUN_00493fe9 0x00493754… lotr2_combat_tick_* Per-type battle tick handlers via PTR_LAB_004f46a0
thunk_FUN_004966c5 0x004966c5 lotr2_siege_pour_boiling_oil Spawns projectile kind 5; sets tile type 10
thunk_FUN_00496931 0x00496931 lotr2_siege_mark_gate_hit Ram contact gate tile flag update
thunk_FUN_0048f83c 0x0048f83c lotr2_siege_open_gate Gate destroyed → tile type 1
thunk_FUN_0048d23a 0x0048d23a lotr2_siege_fire_catapult Catapult aim / type-10 fire; projectile kind 7
FUN_004950fb 0x004950fb lotr2_siege_tick_gate_hack Manual gate hack on tile type 2
FUN_0049422e 0x0049422e lotr2_combat_siege_modify_tile Moat/ladder map terrain modify
DAT_0059c32c 0x0059c32c lotr2_combat_cur_figure Battle tick loop current figure index
DAT_00549552 0x00549552 lotr2_combat_figure_unit_type Figure unit type 0–10 at offset +0x0A
DAT_005496da 0x005496da lotr2_combat_figure_damage_acc 100-point damage pool per soldier
DAT_005496dc 0x005496dc lotr2_combat_figure_attack_damage Melee hit damage from table
DAT_005496e0 0x005496e0 lotr2_combat_figure_head_count Stack / crew count
DAT_005841c7 0x005841c7 lotr2_battle_tile_type Siege map tile object type
DAT_005841c0 0x005841c0 lotr2_battle_tile_damage_ctr Gate/wall hit counter
DAT_005476c9 0x005476c9 lotr2_projectile_kind Projectile kind at slot+0x09
DAT_00543688 0x00543688 lotr2_siege_gate_break_threshold Gate breaks after 15 hits (0xf)

See combat/MODULE.md, ../structs/lotr2_unit_stats.md.

Pass 4 — game winmain startup#

Old symbol Address New symbol Evidence
FUN_004c8559 0x4c8559 lotr2_game_load_lords2_inf Opens lords2.inf; reads 0x41c-byte config block
FUN_004c979f 0x4c979f lotr2_game_check_easter_egg Opens pumkin.wav / swor_p2.wav; sets lotr2_net_join_flags
FUN_004cec91 0x4cec91 lotr2_game_play_intro_or_enable_tick Calls lotr2_video_play_smk or sets tick-pending flag
FUN_004adbc9 0x4adbc9 lotr2_game_init_phase1 Called from lotr2_winmain before phase 2; resets globals
FUN_004af92e 0x4af92e lotr2_game_load_base_assets Loops 13× lotr2_asset_read_file on base01.256 table
FUN_004adb00 0x4adb00 lotr2_game_init_phase2 Second winmain init gate; chains PL8 load on success
FUN_004af1ce 0x4af1ce lotr2_game_reset_pl8_ptrs Zeros 8 PL8 heap pointer globals before reload
FUN_004ae81a 0x4ae81a lotr2_game_load_pl8_assets Loads base1a.pl8 / misc_cty.pl8 slots via lotr2_asset_read_file
FUN_004890df 0x4890df lotr2_game_reset_ui_slots Clears 0x14-byte UI slot table at lotr2_ui_slot_flags
FUN_004adc73 0x4adc73 lotr2_game_shutdown Winmain exit cleanup chain (before gfx release)
FUN_004ca1fc 0x4ca1fc lotr2_ui_show_loading_msg Formats status string into screen buffer; startup milestones
DAT_0050c3a0 0x50c3a0 lotr2_ui_slot_flags 20-slot table cleared by reset-ui-slots
DAT_0050c390 0x50c390 lotr2_ui_slot_count Initialized to 0x14 in reset-ui-slots
DAT_005efe24 0x5efe24 lotr2_game_tick_pending Set by frame-advance and intro path; gates sim tick in idle

See game/MODULE.md.

Pass 5 — game idle tick dispatch#

Old symbol Address New symbol Evidence
FUN_004166f0 0x4166f0 lotr2_game_frame_advance Sets lotr2_game_tick_pending when DAT_0055c02c > 8
FUN_004addaa 0x4addaa lotr2_game_tick_sp Dispatched when lotr2_net_session_active == 0
FUN_004ade2b 0x4ade2b lotr2_game_tick_mp MP path; calls lotr2_net_set_player_ready_flags
FUN_004adf31 0x4adf31 lotr2_game_sim_tick Per-frame sim; loads startXXX.pl8; param_1 = MP flag
FUN_00489129 0x489129 lotr2_game_ui_input_dispatch Routes UI actions from slot flags and game mode

Pass 6 — game sim_tick callees#

Old symbol Address New symbol Evidence
FUN_004c9eaa 0x4c9eaa lotr2_asset_verify_pl8 Opens PL8 with decompress fallback; used for startXXX.pl8, map01.pl8
FUN_004af233 0x4af233 lotr2_game_free_pl8_assets Frees 8 PL8 slot malloc blocks; calls lotr2_game_reset_pl8_ptrs
FUN_004af43b 0x4af43b lotr2_game_free_ui_assets Frees screen/UI malloc blocks before sim tick
FUN_004af721 0x4af721 lotr2_game_free_map_ptrs Frees map-related malloc blocks; calls FUN_004af6ee
FUN_0045ce2a 0x45ce2a lotr2_gfx_mark_fullscreen_dirty Marks the full 640×480 viewport dirty via lotr2_gfx_mark_dirty_rect(0,0,0x27f,0x1df); formerly documented as lotr2_map_blit_fullscreen
FUN_0047a007 0x47a007 lotr2_map_load_pl8_tiles Loops lotr2_asset_verify_pl8 on map01.pl8 variants
FUN_00477610 0x477610 lotr2_map_load_from_dat Reads l2_maps.dat slice into 64×64 province grid

Pass 7 — gfx dirty/present pipeline#

Old symbol Address New symbol Evidence
FUN_0045cd26 0x45cd26 lotr2_gfx_mark_dirty_rect Unions (left,top,right,bottom) into dirty bounds, clamps to 640×480, and sets dirty-pending count
FUN_0045cb80 0x45cb80 lotr2_gfx_present_frame Throttles with lotr2_gfx_frame_delta_ms; presents back buffer to primary surface via DirectDraw surface vtable +0x14/+0x1c
FUN_00436802 0x36802 lotr2_gfx_blt_subrect Builds source/destination rectangles and blits subregions between DirectDraw surfaces
FUN_00436613 0x36613 lotr2_video_is_playing Returns Smacker playback-active flag DAT_00530eec != 0
FUN_004ccea5 0x4ccea5 lotr2_gfx_frame_delta_ms Uses timeGetTime to return elapsed milliseconds and update FPS counters
FUN_004cce16 0x4cce16 lotr2_gfx_surfaces_restorable Checks primary/back surface IsLost via vtable +0x6c before idle tick continues
FUN_004ccd9e 0x4ccd9e lotr2_gfx_on_surface_lost Shows loading message, clears busy flag, and invalidates main window on lost surfaces
FUN_00437799 0x37799 lotr2_gfx_create_surface Builds DDSURFACEDESC and calls IDirectDraw::CreateSurface (vtable +0x18)
DAT_00505360 0x505360 lotr2_gfx_surf_primary DirectDraw primary surface; present destination and lost-surface check target
DAT_00504530 0x504530 lotr2_gfx_surf_backbuf Offscreen back buffer surface; present source and lost-surface check target
DAT_0052931c 0x52931c lotr2_gfx_dirty_pending Pending present counter set by dirty-region markers and decremented after present
DAT_0059b848 0x59b848 lotr2_gfx_use_hicolor 8-bit vs high-color display path gate used by init and present code
DAT_00526748 0x526748 lotr2_gfx_dirty_left Dirty rectangle left bound written by lotr2_gfx_mark_dirty_rect
DAT_00526744 0x526744 lotr2_gfx_dirty_top Dirty rectangle top bound written by lotr2_gfx_mark_dirty_rect
DAT_00529320 0x529320 lotr2_gfx_dirty_right Dirty rectangle right bound written by lotr2_gfx_mark_dirty_rect
DAT_00529318 0x529318 lotr2_gfx_dirty_bottom Dirty rectangle bottom bound written by lotr2_gfx_mark_dirty_rect
FUN_0045ce56 0x45ce56 lotr2_gfx_mark_dirty_tile32 16-pixel tile wrapper marking a 32×32 dirty region
FUN_0045cea9 0x45cea9 lotr2_gfx_mark_dirty_tile48 16-pixel tile wrapper marking a 48×48 dirty region
FUN_0045cefc 0x45cefc lotr2_gfx_mark_dirty_tile64 16-pixel tile wrapper marking a 64×64 dirty region
FUN_0045d048 0x45d048 lotr2_gfx_mark_dirty_tile80x48 16-pixel tile wrapper marking an 80×48 dirty region
FUN_0045d080 0x45d080 lotr2_gfx_mark_dirty_tile80 16-pixel tile wrapper marking an 80×80 dirty region
FUN_0045d0d3 0x45d0d3 lotr2_gfx_mark_dirty_region512x160 16-pixel tile wrapper marking a 512×160 dirty region
FUN_0045d1c6 0x45d1c6 lotr2_gfx_mark_dirty_tiles Generic pixel-origin plus tile-width/height dirty-region marker; can set pending count to 2
FUN_0045d195 0x45d195 lotr2_gfx_mark_dirty_tiles_now Sets force-present flag before delegating to lotr2_gfx_mark_dirty_tiles
FUN_0045ce06 0x45ce06 lotr2_gfx_mark_dirty_partial_screen Marks the right portion of the screen dirty: (0x140,0)..(0x27f,0x1df)
FUN_0045d12a 0x45d12a lotr2_gfx_mark_dirty_status_bar Marks lower status region dirty and arms UI redraw flag
FUN_0045d155 0x45d155 lotr2_gfx_mark_dirty_status_bar_urgent Status-region marker variant that sets dirty-pending count to 2
FUN_0045c9ec 0x45c9ec lotr2_map_set_view_mode Sets map/view scale globals for modes 0, 1, and 2
FUN_0045c990 0x45c990 lotr2_gfx_refresh_fullscreen Marks full screen dirty and forces one present pass
FUN_0045c9aa 0x45c9aa lotr2_gfx_refresh_and_arm_ui Marks full screen dirty and sets UI/game redraw flags

Pass 8 — combat lifecycle and helper sweep#

Pass 8a — battle loop and projectile lifecycle#

Old symbol Address New symbol Evidence
FUN_004907ec 0x004907ec lotr2_combat_init_battle_state Seeds battle state from combat tables, then clears figures/projectiles/groups before setup calls
FUN_004934a2 0x004934a2 lotr2_combat_tick_all_figures Walks active figures 1..0x50; dispatches PTR_LAB_004f46a0[unit_type]; handles oil-spill tiles
FUN_00480a81 0x00480a81 lotr2_combat_clear_all_figures Loops figures 1..0x50 and clears DAT_00549540 + index * 0x1b0
FUN_004804d0 0x004804d0 lotr2_combat_clear_figure_slot Zeroes exactly 0x1b0 bytes, matching recovered battle-figure stride
FUN_00480acf 0x00480acf lotr2_combat_clear_all_projectiles Loops projectile slots 1..0x64 and clears lotr2_projectile_slots + index * 0x4c
FUN_00480509 0x00480509 lotr2_combat_clear_projectile_slot Zeroes exactly 0x4c bytes, matching recovered projectile stride
FUN_004a3166 0x004a3166 lotr2_combat_tick_projectile Reads lotr2_projectile_kind, advances projectile phase, applies terrain/unit effects, and expires slots
FUN_004808cd 0x004808cd lotr2_combat_unlink_projectile_tiles Clears tile occupancy link DAT_005841c6 and projectile next-link fields for active slots
FUN_0048094f 0x0048094f lotr2_combat_link_projectile_tile Inserts projectile index into per-tile list keyed by projectile tile index
FUN_00480575 0x00480575 lotr2_combat_remove_figure Clears tile occupant, optional sprite cleanup, then clears one figure slot
thunk_FUN_0048be59 0x0048be59 lotr2_combat_assign_group_orders Builds combat groups and writes lotr2_combat_group_order_type for active side figures
DAT_005476c0 0x005476c0 lotr2_projectile_slots Base of 100 projectile slots; stride 0x4c per lotr2_projectile docs

Pass 8b — castle layout and siege border#

Old symbol Address New symbol Evidence
FUN_004c8dfb 0x004c8dfb lotr2_siege_load_castle_layout Opens castles.dat, seeks (castle_id - 1) * 0x3200, reads 0x3200 bytes into the battle tile grid
FUN_0041c1ae 0x0041c1ae lotr2_siege_draw_castle_border When siege mode flag is 1, draws left and bottom map borders with line helpers

Pass 8c — combat group and movement helpers#

Old symbol Address New symbol Evidence
FUN_0048030b 0x0048030b lotr2_combat_alloc_group_slot Finds free 0x34-byte group slot, clears it, and stores side/type bytes
FUN_0048053f 0x0048053f lotr2_combat_clear_group_slot Zeroes exactly 0x34 bytes, matching combat group slot stride
FUN_00480b1e 0x00480b1e lotr2_combat_clear_all_group_slots Loops group slots 1..0x50 and clears each 0x34-byte slot
FUN_00480dc5 0x00480dc5 lotr2_combat_direction_from_points Returns one of eight direction codes from source/destination coordinate deltas
FUN_004936ff 0x004936ff lotr2_combat_update_all_move_steps Walks active figures 1..0x50 and calls lotr2_combat_update_walk_anim_step
FUN_004a1f0f 0x004a1f0f lotr2_combat_pop_queued_move_dir Pops queued path coordinates from figure storage and converts them to an 8-way direction
FUN_004a1ffa 0x004a1ffa lotr2_combat_step_figure_tile Moves a figure one tile/index step for direction cases 0..7 and updates tile occupancy

Pass 9 — PL8/256 asset and blit pipeline#

Pass 9a — asset path fallback and Sierra pack decompress#

Old symbol Address New symbol Evidence
FUN_004c9ce8 0x004c9ce8 lotr2_asset_get_extension Copies the three characters after . into the extension scratch buffer
FUN_004c9d58 0x004c9d58 lotr2_asset_set_extension Writes the saved extension back into an existing dotted path
FUN_004c9dca 0x004c9dca lotr2_asset_strip_extension Null-terminates a path at the first . character
FUN_004c9e13 0x004c9e13 lotr2_asset_append_extension Appends . plus the saved extension to the end of a path
FUN_004c9ab0 0x004c9ab0 lotr2_asset_resolve_cd_path First fallback used by lotr2_asset_read_file; rewrites selected extensions to CD/install paths
FUN_004c98b4 0x004c98b4 lotr2_asset_resolve_pk_path Second fallback used by lotr2_asset_read_file; rewrites selected extensions to packed/decompressed paths
FUN_004c9ca0 0x004c9ca0 lotr2_asset_restore_working_path Restores the working path and reports fallback load status
FUN_004cad5e 0x004cad5e lotr2_asset_decompress_sierra_pack Parses embedded palette data and RLE-like pixel payload from packed assets

Pass 9b — PL8/256 loaders and palette upload#

Old symbol Address New symbol Evidence
FUN_0040f895 0x0040f895 lotr2_gfx_load_pl8_screen Reads a PL8 body into the backbuffer from offset 0x18; callers pass 0x1e0 rows
FUN_004116dc 0x004116dc lotr2_gfx_load_pl8_rect Reads a 16-byte PL8 frame header, then reads width * height pixels
FUN_0040f8f5 0x0040f8f5 lotr2_gfx_load_pl8_and_palette Loads a full PL8 screen and companion 0x300-byte .256 palette, then applies it
FUN_0040f989 0x0040f989 lotr2_gfx_load_pl8_decompressed Reads a packed PL8 blob and expands it through lotr2_asset_decompress_sierra_pack
FUN_004cb1f9 0x004cb1f9 lotr2_gfx_apply_palette_rgb Converts 256 RGB triples into DirectDraw palette entries and refreshes the active palette
FUN_00437830 0x00437830 lotr2_gfx_create_dd_palette Calls IDirectDraw::CreatePalette and attaches the palette to the primary surface
FUN_00437bdd 0x00437bdd lotr2_gfx_update_dd_palette Calls IDirectDrawPalette::SetEntries on the active palette
FUN_00437957 0x00437957 lotr2_gfx_build_hicolor_palette_entries Builds high-color palette entries from the game RGB table
FUN_00437a9a 0x00437a9a lotr2_gfx_build_8bit_palette_entries Builds 8-bit DirectDraw palette entries from the game RGB table
FUN_004cb2cd 0x004cb2cd lotr2_gfx_copy_palette_rgb Copies all 256 RGB triples between palette buffers
FUN_004cb348 0x004cb348 lotr2_gfx_palette_scale_down Converts 8-bit RGB components to VGA-style 6-bit components with >> 2
FUN_004cb3a0 0x004cb3a0 lotr2_gfx_palette_scale_up Converts 6-bit RGB components back to 8-bit scale with << 2
DAT_00504268 0x00504268 lotr2_gfx_backbuf_pixels Pointer to the 640x480 software framebuffer used by PL8 loaders and blitters
DAT_00507760 0x00507760 lotr2_gfx_palette_rgb 0x300-byte RGB palette buffer filled by .256 reads
DAT_00505380 0x00505380 lotr2_gfx_backbuf_stride Backbuffer row stride, initialized to 0x280 and used in all pixel offset math

Pass 9c — PL8 sprite blit core#

Old symbol Address New symbol Evidence
FUN_0040f870 0x0040f870 lotr2_gfx_set_blit_mode Sets the blit mode byte and refreshes high-color state when needed
FUN_00409073 0x00409073 lotr2_gfx_blit_clip_x Computes horizontal clipping state and effective width for sprite blits
FUN_004091a0 0x004091a0 lotr2_gfx_blit_clip_y Computes vertical clipping state and source-row offset for sprite blits
FUN_00410ae4 0x00410ae4 lotr2_gfx_blit_sprite_frame Reads a PL8 frame header, clips it, and dispatches to row blit variants
FUN_00410c9a 0x00410c9a lotr2_gfx_blit_sprite_frame_alt Alternate frame draw path that dispatches to the RLE row blit variants
FUN_00410e31 0x00410e31 lotr2_gfx_blit_sprite_frame_noclip Frame draw variant with the same header parse but reduced clip adjustment
FUN_004cfc65 0x004cfc65 lotr2_gfx_blit_opaque_row Copies sprite pixels to the backbuffer while treating palette index 0 as transparent
FUN_004cfd21 0x004cfd21 lotr2_gfx_blit_clip_left_row Left-clipped variant of the transparent row copy
FUN_004cfd86 0x004cfd86 lotr2_gfx_blit_clip_right_row Right-clipped variant of the transparent row copy
FUN_004cfdeb 0x004cfdeb lotr2_gfx_blit_opaque_row_alt Alternate RLE-style row blit used by lotr2_gfx_blit_sprite_frame_alt
FUN_004d00c8 0x004d00c8 lotr2_gfx_blit_clip_left_row_alt Left-clipped alternate RLE row blit
FUN_004d016c 0x004d016c lotr2_gfx_blit_clip_right_row_alt Right-clipped alternate RLE row blit
FUN_004d02ab 0x004d02ab lotr2_gfx_blit_tile16_strip Copies a 16x16 tile strip into the backbuffer using the global blit origin
FUN_004d056c 0x004d056c lotr2_gfx_blit_tile16_block Full 16x16 tile block copy variant

Pass 9d — tile grids and UI panel borders#

Old symbol Address New symbol Evidence
FUN_0040fa15 0x0040fa15 lotr2_gfx_blit_tile16_grid_bordered Draws a 16x16 tile grid with edge and corner tile selection
FUN_0040fb44 0x0040fb44 lotr2_gfx_blit_tile16_grid_flat Draws a flat 16x16 tile grid using one tile index
FUN_0040fc10 0x0040fc10 lotr2_gfx_draw_panel_bordered Draws a bordered panel, then fills the interior
FUN_0040fc61 0x0040fc61 lotr2_gfx_draw_panel_style0 Panel drawing wrapper for style 0 corner and fill tiles
FUN_0040fcaa 0x0040fcaa lotr2_gfx_draw_panel_style1 Panel drawing wrapper for style 1 corner and fill tiles
FUN_0040fcf3 0x0040fcf3 lotr2_gfx_draw_panel_style2 Panel drawing wrapper for style 2 corner and fill tiles
FUN_0040fd37 0x0040fd37 lotr2_gfx_blit_panel_border_tiles Emits the border tile strip for panel frames
FUN_0041008f 0x0041008f lotr2_gfx_blit_panel_inner_fill Fills the interior panel region after border draw
FUN_004101fe 0x004101fe lotr2_gfx_blit_panel_corner_set Selects corner/cap tile set based on style parameter
FUN_0041055d 0x0041055d lotr2_gfx_blit_panel_edge_fill Fills panel edge spans between selected corners
FUN_004106d3 0x004106d3 lotr2_gfx_blit_panel_edge_fill_alt Alternate edge-fill helper used by panel variants
FUN_004108e7 0x004108e7 lotr2_gfx_blit_sprite_scaled Draws a scaled rectangular sprite region after PL8 rect loads

Pass 10 — combat figure animation steps#

Old symbol Address New symbol Evidence
FUN_00496f63 0x00496f63 lotr2_combat_update_walk_anim_step Callee of lotr2_combat_update_all_move_steps; thin wrapper to walk sprite advance
FUN_00498008 0x00498008 lotr2_combat_advance_walk_sprite Uses lotr2_combat_cur_figure and lotr2_combat_figure_unit_type; advances frame at figure+0x4b; sets sprite index at +0x50; siege types call lotr2_combat_siege_update_sprite_a
FUN_00496f73 0x00496f73 lotr2_combat_update_counter_anim_step Called when figure+0x186 counter-attack flag set; wrapper to counter sprite
FUN_00498662 0x00498662 lotr2_combat_advance_counter_sprite Same unit-type branching as walk; advances counter frame at figure+0x4e
FUN_00496f83 0x00496f83 lotr2_combat_update_idle_anim_step Called from lotr2_combat_siege_modify_tile after clearing figure+0x01
FUN_00498a3e 0x00498a3e lotr2_combat_advance_idle_sprite Sets idle sprite from figure+0x16b phase; siege types call lotr2_combat_siege_update_sprite_b
FUN_00496f93 0x00496f93 lotr2_combat_update_fire_anim_step Called when figure+0x16c fire flag set during ranged/projectile ticks
FUN_00498da4 0x00498da4 lotr2_combat_advance_fire_sprite Archer/crossbow fire sprite from facing and 0x004f4e38 table; uses DAT_0055bfdc facing quadrant

Pass 11 — map province load (sim_tick callees)#

Old symbol Address New symbol Evidence
FUN_00479f3d 0x00479f3d lotr2_map_load_pl8_province_tiles Selects map01.pl8 variant; reads 0x4000 bytes into province tile buffers; lotr2_ui_show_loading_msg
FUN_0047a078 0x0047a078 lotr2_map_clear_province_rect Walks 64×64 province grid region; stride-8 cell index from (y*0x40+x)*8
FUN_0047a167 0x0047a167 lotr2_map_clear_province_cell Clears one province cell in DAT_00552180 table; rotates DAT_00563d14 tile index

Pass 12 — UI screen action queue#

Old symbol Address New symbol Evidence
FUN_00489419 0x00489419 lotr2_game_ui_queue_screen_action Callee of lotr2_game_ui_input_dispatch; sets screen mode 0x27; flags slot in DAT_0050c2d8
FUN_00489491 0x00489491 lotr2_game_ui_restore_screen_mode Restores prior screen from DAT_0050c398 when mode is 0x27; resets lotr2_ui_slot_count

Pass 13 — game sim_tick init chain#

Old symbol Address New symbol Evidence
FUN_004afaf1 0x004afaf1 lotr2_game_load_system_ui_pl8 Loads system2.pl8 variant via lotr2_asset_read_file; called from sim tick and idle render
FUN_004af109 0x004af109 lotr2_game_load_misc_sel_pl8 Frees PL8/UI/map assets then loads misc_sel.PL8 into malloc buffer
FUN_004346a1 0x004346a1 lotr2_map_init_province_grid Clears 0x81×0x41 province index grid; sets DAT_0055bfdc facing; fills visible tile indices
FUN_0047781d 0x0047781d lotr2_map_seed_grid_from_dat Reads l2_maps.dat slice and seeds province grid cells from map byte table
FUN_004c896d 0x004c896d lotr2_game_set_difficulty_tier Maps param 0..5+ to difficulty index DAT_0059b8a8 (0..3)
FUN_0043ba95 0x0043ba95 lotr2_game_sync_ui_scroll_offset Recomputes UI scroll offset DAT_0059b888 from season counter
FUN_004ae5ae 0x004ae5ae lotr2_game_reset_map_state Resets map/view globals; calls lotr2_map_init_province_grid and lotr2_map_set_view_mode
FUN_004af6ee 0x004af6ee lotr2_game_clear_map_ptrs Zeros four map malloc pointer globals; callee of lotr2_game_free_map_ptrs

Pass 14 — map load pipeline + province topology#

Old symbol Address New symbol Evidence
FUN_00477580 0x00477580 lotr2_map_load_new_game New-game entry; sequences layer clear, dat load, PL8, neighbors, province setup
FUN_0047c48a 0x0047c48a lotr2_map_clear_province_layers Zeros 8 parallel 64×64 layers indexed by param_1
FUN_0047de23 0x0047de23 lotr2_map_clear_cell_highlights Clears bit 0x20 on all cells; calls lotr2_gfx_mark_fullscreen_dirty
FUN_0047dac7 0x0047dac7 lotr2_map_paint_visible_grid Walks 0x81×0x41 DAT_005934e0; paints cells from tile index
FUN_0047dc06 0x0047dc06 lotr2_map_paint_sea_tiles Sets sea sentinel 0xfff0006 tiles in visible grid
FUN_00477bc4 0x00477bc4 lotr2_map_build_province_neighbors Fills DAT_0055c40c adjacency lists via neighbor scan
FUN_004778d6 0x004778d6 lotr2_map_place_starting_units Difficulty-tier unit placement on cells with flag 0x20
FUN_0047d91d 0x0047d91d lotr2_map_build_army_slot_table Maps starting units into DAT_00580bc0 per-province slots
FUN_00478c6d 0x00478c6d lotr2_map_setup_all_provinces Per-province loop: castle, special tiles, keep, farm
FUN_00477eef 0x00477eef lotr2_map_find_castle_cell Finds 4th castle tile (flag 0x40); stores DAT_0055c420
FUN_0047803f 0x0047803f lotr2_map_find_keep_cell Finds keep tile (flag 0x80); stores DAT_0055c428
FUN_00478b5f 0x00478b5f lotr2_map_collect_special_tiles Collects 0x10-flag tiles into DAT_0055c430
FUN_00478d7f 0x00478d7f lotr2_map_locate_province_structures Marks town/castle/capital cells on grid
FUN_00478f48 0x00478f48 lotr2_map_place_province_farm Places farm tile nearest to capital coords
FUN_00477d4a 0x00477d4a lotr2_map_province_has_neighbor Membership test in DAT_0055c40c list
FUN_00477dce 0x00477dce lotr2_map_provinces_are_neighbors Bidirectional adjacency via neighbor lists
FUN_00477e4c 0x00477e4c lotr2_map_province_has_hostile_neighbor Hostile-neighbor check for diplomacy
FUN_0047aaf4 0x0047aaf4 lotr2_map_stamp_tile_block Stamps N×N tile block on province grid
FUN_0047d6c6 0x0047d6c6 lotr2_map_set_cell_display Updates cell tile index + sprite char at offset

Pass 15 — map province runtime / tile mutation#

Old symbol Address New symbol Evidence
FUN_0047818a 0x0047818a lotr2_map_draw_capital_tiles Stamps capital marker via lotr2_map_stamp_tile_block
FUN_00478267 0x00478267 lotr2_map_restore_province_tiles Restores 2×2 province tile sprites from backup
FUN_0047833a 0x0047833a lotr2_map_clear_province_armies Clears army units tied to province capital
FUN_004783e4 0x004783e4 lotr2_map_set_special_tile_levels Adjusts special-tile display levels (0x10–0x13)
FUN_004785be 0x004785be lotr2_map_transfer_province_gold Gold transfer between provinces
FUN_0047865d 0x0047865d lotr2_map_transfer_province_food Food transfer between provinces
FUN_00478a00 0x00478a00 lotr2_map_transfer_province_wood Wood transfer between provinces
FUN_0047913b 0x0047913b lotr2_map_recount_province_armies Recounts armies; dispatches food/gold handlers
FUN_004791c5 0x004791c5 lotr2_map_snapshot_army_tiles Copies 0x14 army slot tile states to scratch
FUN_0047928e 0x0047928e lotr2_map_restore_army_tiles Restores army slot tiles from snapshot
FUN_0047934a 0x0047934a lotr2_map_clear_province_army_slot Clears one army slot cell
FUN_004793dd 0x004793dd lotr2_map_assign_army_to_slot Assigns army cell index to province slot
FUN_004794ad 0x004794ad lotr2_map_apply_gold_upkeep Province gold upkeep from army counts
FUN_00479578 0x00479578 lotr2_map_apply_food_upkeep Province food upkeep from army counts
FUN_004796eb 0x004796eb lotr2_map_paint_province_rect Paints tile type across province rect
FUN_004797ab 0x004797ab lotr2_map_fill_province_rect Fills rect with terrain flags
FUN_00479c3f 0x00479c3f lotr2_map_update_province_tiles_in_range Bulk tile update filtered by province + type range
FUN_00479d2c 0x00479d2c lotr2_map_cell_has_army_unit Returns whether cell holds an army unit
FUN_00479d79 0x00479d79 lotr2_map_clear_cell_with_upkeep Clears cell; adjusts province gold/food counters
FUN_00479aab 0x00479aab lotr2_map_count_province_armies Tallies army types into province counters
FUN_00479a6f 0x00479a6f lotr2_map_recount_all_armies Loops all provinces through army recount

Pass 16 — l2_maps.dat parse helpers#

Old symbol Address New symbol Evidence
FUN_00433901 0x00433901 lotr2_map_clear_layer_province_lists Zeros 6×16 province-id list at DAT_0055b750 and 6 summary bytes at DAT_00573bc0; called once at start of dat load
FUN_004b1e75 0x004b1e75 lotr2_map_clear_province_slot_pairs Zeros 6 (province_id, slot_index) pairs at DAT_0055ac00; called once at start of dat load
FUN_00433984 0x00433984 lotr2_map_append_province_to_layer (province_id, layer_index): first-fit append into layer row of DAT_0055b750; called when cell flag 0x40 and index byte non-zero
FUN_004b1e40 0x004b1e40 lotr2_map_set_province_slot_pair (province_id, slot_index): writes pair to DAT_0055ac00, increments DAT_00582d34; called when cell flag 0x80 and index byte non-zero

Pass 17 — save/load core I/O#

Old symbol Address New symbol Evidence
FUN_004c823e 0x004c823e lotr2_save_load_from_file Opens save (0x8301); writes field-table blocks via FUN_004e4da0; reads 16×0x3200 from castles.dat; used for load + lastturn.* continue
FUN_004c838c 0x004c838c lotr2_save_write_to_file Opens save for write (0x8000); reads field-table blocks via __read; writes 16×0x3200 to castles.dat
FUN_004c9520 0x004c9520 lotr2_save_enum_files FindFirstFileA/FindNextFileA on *.sav/.sva/.svb; fills filename table at DAT_00504900
FUN_004c965b 0x004c965b lotr2_save_sort_file_list Bubble-sorts enumerated filenames; callee of lotr2_save_enum_files
FUN_004c8500 0x004c8500 lotr2_game_write_lords2_inf Writes 0x41c bytes from lotr2_game_config_block to lords2.inf
FUN_004c89cd 0x004c89cd lotr2_save_read_inf_fields Reads 100-entry field table at DAT_004fa230/234 from opened file
FUN_004c8a6c 0x004c8a6c lotr2_save_sanitize_filename Pads/truncates filename buffer to 0x20 chars; strips control bytes
PTR_DAT_004fa280 0x004fa280 lotr2_save_field_ptrs Pointer column of main save field table (up to 500 entries)
DAT_004fa284 0x004fa284 lotr2_save_field_sizes Size column; loop terminates when size == 0

Pass 18 — save/load lords2.inf defaults#

Old symbol Address New symbol Evidence
FUN_004c864a 0x004c864a lotr2_save_inf_stub Empty placeholder; called from lotr2_game_load_lords2_inf load path
FUN_004c865c 0x004c865c lotr2_save_inf_on_load_success After lords2.inf read: increments load counter or resets defaults
FUN_004c86af 0x004c86af lotr2_save_inf_init_defaults Seeds lotr2_game_config_block config block with default gameplay/audio values
FUN_004c88c4 0x004c88c4 lotr2_save_inf_init_audio_tiers Sets difficulty/audio tier defaults; branches on lotr2_net_session_active
DAT_004fa230 0x004fa230 lotr2_save_inf_field_ptrs Pointer column of smaller inf field table (100 entries)
DAT_004fa234 0x004fa234 lotr2_save_inf_field_sizes Size column for inf field table
DAT_00504544 0x00504544 lotr2_save_file_count Count from enum; used in lotr2_game_load_lords2_inf
DAT_00504900 0x00504900 lotr2_save_file_names 100 × 0xd-byte filename table from enum

Pass 19 — save/load UI flow#

Old symbol Address New symbol Evidence
FUN_004c7de0 0x004c7de0 lotr2_save_ui_debounce_dispatch Screen-mode timer; dispatches save (0x1f), save-as ('5'), load ('6') via write/load helpers + MP net messages
FUN_004c80a1 0x004c80a1 lotr2_save_wait_mp_ready Post-save MP sync loop (timeGetTime, player-ready flags at DAT_005814c0)
FUN_004adc92 0x004adc92 lotr2_save_restart_after_load Post-save/load world rebuild: map grid, PL8 tiles, army slots, screen mode
FUN_004b0c1e 0x004b0c1e lotr2_save_continue_lastturn Screen '$' handler; loads lastturn.sav/.sva/.svb by role
DAT_005d9c78 0x005d9c78 lotr2_save_write_ok Set to 1 after successful save write
DAT_005bc724 0x005bc724 lotr2_save_io_failed Non-zero when save/load I/O returns error; gates debounce retry

Pass 20 — net app-message handlers#

173 pack/unpack handlers renamed from layout at 0x449e000x44ee00 (90 opcodes, consecutive pack/unpack pairs; opcodes 8–9 have no distinct handlers in this layout). Full list: run python3 tools/ghidra/generate_net_handler_renames.py.

Semantic handlers (documented)#

Old symbol Address New symbol Evidence
FUN_00449eaf 0x00449eaf lotr2_net_unpack_join_handshake_request Opcode 1 unpack; payload_read 4+0x20+4; mirrors lotr2_net_pack_local_id
FUN_0044a0d0 0x0044a0d0 lotr2_net_pack_player_roster_sync Opcode 3 pack; 145-byte roster fields
FUN_0044a36a 0x0044a36a lotr2_net_unpack_player_roster_sync Opcode 3 unpack; matching payload_read
FUN_0044ab11 0x0044ab11 lotr2_net_pack_heartbeat_toggle Opcode 10 pack; unreliable send path
FUN_0044ab51 0x0044ab51 lotr2_net_unpack_heartbeat_toggle Opcode 10 unpack
FUN_00449e61 0x00449e61 lotr2_net_pack_opcode_00 Opcode 0 pack stub
FUN_00449e6c 0x00449e6c lotr2_net_unpack_opcode_00 Opcode 0 unpack stub

Sync / session helpers#

Old symbol Address New symbol Evidence
FUN_00448e65 0x00448e65 lotr2_net_refresh_player_sync_checksums Clears msg history; sums per-player sync bytes via FUN_00448d8e
FUN_0044927a 0x0044927a lotr2_net_host_check_sync_ready Host-only; calls compare helper; sends opcode 0xf when ready
FUN_004493e9 0x004493e9 lotr2_net_compare_player_sync_slot Compares DAT_005494c0 row across player slots
FUN_00449553 0x00449553 lotr2_net_apply_host_sync_masks Applies DAT_00573bfc bits; client sends opcode 0x12
FUN_0043b22b 0x0043b22b lotr2_net_sync_local_faction_id Writes DAT_0059bc21 from local slot; callee of lotr2_net_start_session

Pass 21 — game screen state machine#

Screen-state globals#

Old symbol Address New symbol Evidence
DAT_00507ab8 0x00507ab8 lotr2_game_screen_mode Central switch key (831 refs); set to 0x1f by lotr2_game_sim_tick on new game
DAT_0059347c 0x0059347c lotr2_game_screen_phase Paired with screen_mode in transitions (= 1 init / = 2 active)
DAT_00593494 0x00593494 lotr2_game_wizard_step Sub-step within mode 0x1f (save/load, MP lobby wizard)
DAT_005d9c88 0x005d9c88 lotr2_game_turn_phase Set 1–4 by turn-phase action handlers

Click dispatch chain#

Old symbol Address New symbol Evidence
FUN_0043a2e7 0x0043a2e7 lotr2_game_screen_tick Large per-frame handler; branches on lotr2_game_screen_mode
FUN_0043a78c 0x0043a78c lotr2_game_dispatch_click Routes to map vs panel click by DAT_0059c220
FUN_0043a8c8 0x0043a8c8 lotr2_game_handle_map_click Hit-tests map grid DAT_0055f500; selects province
FUN_0043a7d1 0x0043a7d1 lotr2_game_handle_panel_click Viewport bounds check; calls map blit or battle prep
FUN_0043ab19 0x0043ab19 lotr2_game_select_province Called from map click; sets province scroll and DAT_0055ab10

Turn-phase action handlers#

Old symbol Address New symbol Evidence
FUN_0043c007 0x0043c007 lotr2_game_reset_lobby_flags Clears DAT_005bc768, sets DAT_005bc728
FUN_0043c023 0x0043c023 lotr2_game_action_enter_mode_0x39 Host/client gate; sets screen mode 0x39 or sends net msg
FUN_0043c087 0x0043c087 lotr2_game_action_toggle_flag_b87c Turn phase 1; toggles DAT_0059b87c; MP sends opcode 0x32
FUN_0043c101 0x0043c101 lotr2_game_action_end_turn Turn phase 2; per-player economy/diplomacy loop
FUN_0043c1c4 0x0043c1c4 lotr2_game_action_toggle_flag_b884 Turn phase 3; toggles DAT_0059b884
FUN_0043c23e 0x0043c23e lotr2_game_action_toggle_flag_b8a4 Turn phase 4; toggles DAT_0059b8a4

See game/MODULE.md.

Pass 22 — combat/siege init and tick helpers#

See combat/MODULE.md.

Slot / state clearing#

Old symbol Address New symbol Evidence
FUN_00480b6d 0x00480b6d lotr2_combat_clear_all_spawn_records Loops 0x11×; clears 0x300-byte slots from DAT_0055c3b0
FUN_00480bb0 0x00480bb0 lotr2_combat_clear_all_troop_entries Loops 6×; clears 0x160-byte slots from lotr2_game_ai_player_step
FUN_00480bf8 0x00480bf8 lotr2_combat_clear_all_troop_orders Loops 6×; clears 0x2c-byte slots from DAT_0055a900
FUN_00480c3f 0x00480c3f lotr2_combat_clear_all_flag_slots Loops 0xd×; clears 0x14-byte slots from DAT_00582ff0
FUN_00480c82 0x00480c82 lotr2_combat_clear_battle_tile_occupancy Zeros tile occupancy bits; walks 0x97 active slots
FUN_00480d5e 0x00480d5e lotr2_combat_clear_all_province_armies Loops 0x97×; clears 0x1a4-byte province army records
FUN_00480dac 0x00480dac lotr2_combat_stub_return_zero Single-instruction stub return 0

Battle map init / pathfinding#

Old symbol Address New symbol Evidence
FUN_00483570 0x00483570 lotr2_combat_init_pathfinding_grid Fills 80×80 array with 0 or 999 from tile bit 0x10
FUN_00483662 0x00483662 lotr2_combat_pack_tile_heights Copies height byte into compact 80×80 byte array
FUN_004836d8 0x004836d8 lotr2_combat_init_wall_adjacency_map Marks tiles adjacent to type-1 facing type-5 as cost 4
FUN_004837f2 0x004837f2 lotr2_combat_mark_figure_tiles_blocked Sets pathfinding cell 0x3e6 for friendly figure tiles

Battle session entry / exit#

Old symbol Address New symbol Evidence
FUN_00488769 0x00488769 lotr2_combat_draw_unit_info_panel Draws unit portrait, name, stats; branches on unit category
FUN_00488dea 0x00488dea lotr2_combat_exit_to_campaign Stops audio; restores campaign screen mode
FUN_0048b180 0x0048b180 lotr2_combat_enter_open_battle Calls lotr2_combat_init_battle_state; sets screen mode 0x2c
FUN_0048b35b 0x0048b35b lotr2_combat_start_battle_music Picks battle1_wav/battle2_wav by siege and MP mode
FUN_0048b469 0x0048b469 lotr2_combat_enter_siege_battle Loads castle layout; inits pathfinding and figures
FUN_0048b58d 0x0048b58d lotr2_combat_check_battle_outcome Detects zero-headcount side; sets defeat screen mode 0x30

Siege tile / gate state#

Old symbol Address New symbol Evidence
FUN_0048f752 0x0048f752 lotr2_siege_clear_tile_gate_face Sets tile byte 0xed; clears flag nibble
FUN_0048f784 0x0048f784 lotr2_siege_set_tile_gate_closed Sets tile type 2; sets bit 0x10; reloads owner color
FUN_0048f99e 0x0048f99e lotr2_siege_set_tile_drawbridge_open Sets tile type 9; rebuilds adjacent type-5 tiles
FUN_0048fb9a 0x0048fb9a lotr2_siege_set_tile_owner_color Writes lower nibble of DAT_005bc588 into tile color
FUN_0048fbee 0x0048fbee lotr2_siege_init_castle_tile_layout Top-level castle init; six sub-passes
FUN_0048fc21 0x0048fc21 lotr2_siege_flood_fill_exterior Flood-fill reachable tiles → type 6 (exterior ground)
FUN_0048fd45 0x0048fd45 lotr2_siege_flood_fill_wall_face Flood-fill assigns tile type 5 (wall face)

Figure state setup / input#

Old symbol Address New symbol Evidence
FUN_0049055b 0x0049055b lotr2_combat_place_figures_on_tiles Writes figure slot into tile occupancy
FUN_004905e1 0x004905e1 lotr2_combat_clamp_scroll_pos Clamps battle scroll position to map bounds
FUN_00490648 0x00490648 lotr2_combat_handle_map_click Mouse coords → tile; resolves selected figure
FUN_00490b60 0x00490b60 lotr2_combat_load_formation_thresholds Loads formation tier thresholds from 0x4f4b28
FUN_00490ba7 0x00490ba7 lotr2_combat_tally_army_survivors Sums surviving infantry back into province army records
FUN_00490e96 0x00490e96 lotr2_combat_compute_unit_score Weighted strength score by unit type multiplier
FUN_00491077 0x00491077 lotr2_combat_rout_player_figures Sets all figures of player to routing state
FUN_00492127 0x00492127 lotr2_combat_reset_figure_move_targets Clears move-target field for all active figures
FUN_00492184 0x00492184 lotr2_combat_assign_figure_sprite_ptrs Assigns sprite pointers by unit type and side
FUN_00492634 0x00492634 lotr2_combat_set_group_siege_order_type Scans group for siege units; assigns order 5–8

Unit hover / tooltip#

Old symbol Address New symbol Evidence
FUN_00489505 0x00489505 lotr2_combat_draw_figure_tooltip Draws hover tooltip; marks tile dirty
FUN_004896aa 0x004896aa lotr2_combat_clear_figure_hover Clears hover slot; redraws tile
FUN_00489728 0x00489728 lotr2_combat_confirm_figure_hover Confirms hover; writes sprite cache
FUN_004897a1 0x004897a1 lotr2_combat_poll_figure_hover timeGetTime poll; computes tooltip position
FUN_004898b9 0x004898b9 lotr2_combat_clamp_tooltip_pos Clamps tooltip screen coordinates

Pass 23 — combat projectile, pathfind, and figure tick helpers#

See combat/MODULE.md.

Projectile / figure memory helpers#

Old symbol Address New symbol Evidence
FUN_0048009f 0x0048009f lotr2_combat_probe_los_neighbors Loops 0x14 iterations; calls thunk_FUN_004a5b44(x,y,i); returns 0/1 — LOS neighbor scan
FUN_004800f8 0x004800f8 lotr2_combat_alloc_projectile_slot Scans slots 1..100 at stride 0x4c; writes position fields; calls lotr2_combat_direction_from_points — mirrors lotr2_combat_clear_projectile_slot
FUN_00480461 0x00480461 lotr2_combat_zero_figure_bytes Zeroes exactly 0x1a4 bytes from param_1 — province army record size
FUN_004803b9 0x004803b9 lotr2_combat_zero_group_bytes_300 Zeroes 0x300 bytes; called from lotr2_combat_clear_all_spawn_records
FUN_0048042b 0x0048042b lotr2_combat_zero_group_bytes_2c Zeroes 0x2c bytes; called from lotr2_combat_clear_all_troop_orders
FUN_004805ff 0x004805ff lotr2_combat_unlink_province_army_tile Walks linked list at DAT_005643d4; removes province army from tile occupancy chain — pair of FUN_00480770
Old symbol Address New symbol Evidence
FUN_004818c5 0x004818c5 lotr2_combat_build_path_cost_grid Nested 0x40 loops over DAT_00552181/DAT_00552180; writes cost table at DAT_00518f10
FUN_00481b2e 0x00481b2e lotr2_combat_pathfind_query_neighbor Traces 8-way path from (param_2,param_3) through cost grid; stores waypoint list; returns 1
FUN_0048101f 0x0048101f lotr2_combat_reset_pathfind_search Clears side-specific pathfind buffer (0x2000); sets origin tile coords; calls pathfind init helper

Projectile tile marking#

Old symbol Address New symbol Evidence
FUN_004932c6 0x004932c6 lotr2_combat_mark_projectile_tiles Siege mode (DAT_0059c220==2); loops projectile slots; sets DAT_005841c2 dirty bits under active projectiles

Figure state-machine tick handlers (PTR_LAB_004f46d0)#

Old symbol Address New symbol Evidence
FUN_004936f4 0x004936f4 lotr2_combat_tick_stub_936f4 Empty stub; dispatch table slot
FUN_004940cb 0x004940cb lotr2_combat_tick_stub_940cb Empty stub; dispatch table slot
FUN_004940d6 0x004940d6 lotr2_combat_tick_figure_walk Calls lotr2_combat_update_walk_anim_step; decrements walk counter at stride 0x1b0; may call ranged fire
FUN_0049436e 0x0049436e lotr2_combat_tick_figure_move Calls move-step helper; updates walk anim on flag bit 0x02
FUN_004943f8 0x004943f8 lotr2_combat_tick_figure_melee_engage Calls lotr2_combat_apply_melee_hit when target state is 4; reads target slot at DAT_005496be
FUN_0049450a 0x0049450a lotr2_combat_tick_figure_walk_and_fire Walk anim step; conditionally calls ranged fire when DAT_005496aa set
FUN_00494557 0x00494557 lotr2_combat_tick_figure_ranged_fire Infantry types 0–6; calls lotr2_combat_alloc_projectile_slot; writes lotr2_projectile_kind

Pass 24 — game screen mode hub#

See game/MODULE.md.

Screen mode tick hub#

Old symbol Address New symbol Evidence
FUN_00438b90 0x00438b90 lotr2_game_screen_mode_tick Main per-frame handler; branches on lotr2_game_screen_mode; 47 unnamed callees; ends at LAB_0043a2b3
FUN_0043a5af 0x0043a5af lotr2_game_pick_scroll_dir Computes 8-way scroll direction in DAT_00573c00; calls lotr2_game_screen_tick
FUN_0043a9ce 0x0043a9ce lotr2_game_ui_scroll_bar_hit First callee from hub; sets scroll-bar hit zone _DAT_0059c384 from mouse coords
FUN_004d65fc 0x004d65fc lotr2_game_validate_scroll Sole unnamed callee of lotr2_game_screen_tick; timeGetTime debounce before applying scroll

Campaign UI hit tests (hub callees)#

Old symbol Address New symbol Evidence
FUN_0043acbb 0x0043acbb lotr2_game_ui_hit_test_campaign_toolbar Hit test 4 buttons at (0x262,0x20) via FUN_004159ce / DAT_004f8100
FUN_0043acf5 0x0043acf5 lotr2_game_ui_hit_test_status_buttons Hit test 6 buttons at (0x1de,0x1ae) / DAT_004f8160
FUN_0043ac21 0x0043ac21 lotr2_game_ui_mark_panel_dirty Marks gfx dirty region from panel rect table DAT_004f03d8
FUN_0043ad32 0x0043ad32 lotr2_game_ui_hit_test_battle_toolbar Hit test 5 buttons at (0x1e0,0x1c0); used in battle screen mode ','
FUN_0043ad7a 0x0043ad7a lotr2_game_on_mp_lobby_start Mode 0x1c lobby complete; sends net msg 4 or starts SP sim; sets lotr2_game_screen_phase
FUN_0043bd77 0x0043bd77 lotr2_game_ui_hit_test_save_slot Save-slot grid hit test in wizard modes 5/6 and wizard step 3
FUN_0043cbd2 0x0043cbd2 lotr2_game_return_to_campaign_map Cancel to campaign; restores scroll, loads PL8, sets screen phase
FUN_0043aad4 0x0043aad4 lotr2_game_select_province_by_tile_index Select province by tile grid index param
FUN_00440725 0x00440725 lotr2_game_ui_hit_test_army_panel Army panel quadrant hit test (0x1e7–0x276, 0xb5–0xf1)
FUN_00440875 0x00440875 lotr2_game_ui_hit_test_build_menu Build menu item hit test; sets build action DAT_0055a374
FUN_00440ab3 0x00440ab3 lotr2_game_ui_on_panel_overview_click Overview panel dismiss click; clears DAT_0055ac38
FUN_00440b5c 0x00440b5c lotr2_game_ui_hit_test_tax_slider Tax rate slider hit test; updates DAT_00582ddc

End-turn economy / diplomacy#

Old symbol Address New symbol Evidence
FUN_00456516 0x00456516 lotr2_game_economy_tick_player Callee of lotr2_game_action_end_turn; per-player tax/income loop
FUN_00451511 0x00451511 lotr2_game_diplomacy_tick_player Callee of lotr2_game_action_end_turn; army count + diplomacy tick chain

Pass 25 — game hub leaf callees#

See game/MODULE.md.

Old symbol Address New symbol Evidence
FUN_00415da6 0x00415da6 lotr2_game_ui_hit_test_dialog_ok ~25× callee of lotr2_game_screen_mode_tick; 0x18×0x18 hit rect when DAT_00505421; calls thunk_FUN_004cc027 on hit
FUN_0041c2f0 0x0041c2f0 lotr2_game_clear_bottom_panel_rows Hub callee on dialog dismiss (modes 2, 0xf); clears screen rows 0x1da–0x1df via thunk_FUN_004cf90a
FUN_00444488 0x00444488 lotr2_game_mark_status_bar_dirty Thin wrapper calling lotr2_gfx_mark_dirty_status_bar; hub callee on mode-4 scroll paths
FUN_00480770 0x00480770 lotr2_combat_link_province_army_tile Pair of lotr2_combat_unlink_province_army_tile; links 0x1a4-byte province army into tile occupancy list at DAT_00552185
FUN_0043ae19 0x0043ae19 lotr2_game_wizard_on_mp_host Branches on lotr2_game_turn_phase; phase 2 calls lotr2_net_start_session, sets lotr2_game_wizard_step, plays s011_02_wav
FUN_0043af56 0x0043af56 lotr2_game_wizard_on_save_step Wizard turn-phase dispatch; phases 1–4 set lotr2_game_wizard_step and save/load audio cues (s011_02_wav)
FUN_0043bf96 0x0043bf96 lotr2_game_ui_draw_modal_backdrop Callee of lotr2_game_ui_input_dispatch; blits 0xa0×0xa0 modal via FUN_00415cb4

Pass 26 — turn-action table (0x43c000)#

See game/MODULE.md.

Old symbol Address New symbol Evidence
FUN_0043c2b8 0x0043c2b8 lotr2_game_action_toggle_flag_b86c Toggles DAT_0059b86c; calls lotr2_game_reset_ui_slots; sets lotr2_game_screen_phase
FUN_0043c2f8 0x0043c2f8 lotr2_game_action_toggle_flag_b870 Toggles DAT_0059b870; clears _DAT_00507754 scroll state
FUN_0043c33d 0x0043c33d lotr2_game_action_mp_send_0x123 MP client gate; thunk_FUN_00485655(…,0x123,…) then restore lotr2_game_screen_mode
FUN_0043c37b 0x0043c37b lotr2_game_action_mp_send_0x124 Same pattern with net opcode 0x124
FUN_0043c3b9 0x0043c3b9 lotr2_game_action_mp_send_0x125 Same pattern with net opcode 0x125
FUN_0043c3f7 0x0043c3f7 lotr2_game_action_mp_send_0x126 Same pattern with net opcode 0x126
FUN_0043c435 0x0043c435 lotr2_game_action_mp_send_0x127 Same pattern with net opcode 0x127
FUN_0043c473 0x0043c473 lotr2_game_action_show_help WinHelpA(lotr2_ui_hwnd_main, s_l2help_hlp, 3, 1)
FUN_0043c49d 0x0043c49d lotr2_game_action_enter_mode_0x42 Sets lotr2_game_screen_mode = 0x42
FUN_0043c4b9 0x0043c4b9 lotr2_game_action_enter_mode_0x43 Sets lotr2_game_screen_mode = 0x43
FUN_0043c4d5 0x0043c4d5 lotr2_game_action_toggle_music Toggles DAT_0059b838; stops/starts campaign (FUN_004afb9f) or battle (lotr2_combat_start_battle_music) audio
FUN_0043c55a 0x0043c55a lotr2_game_action_toggle_sfx Toggles DAT_0059b834; calls FUN_004afe52 / FUN_004afe6c by DAT_0059c220
FUN_0043c5cb 0x0043c5cb lotr2_game_action_toggle_flag_b82c Toggles DAT_0059b82c
FUN_0043c606 0x0043c606 lotr2_game_action_toggle_flag_b868 Toggles DAT_0059b868
FUN_0043c641 0x0043c641 lotr2_game_action_toggle_hicolor Toggles lotr2_gfx_use_hicolor; re-inits DirectDraw or sends net msg 0x104/299

Pass 27 — campaign UI cluster (0x440000)#

See game/MODULE.md.

Old symbol Address New symbol Evidence
FUN_004423f7 0x004423f7 lotr2_game_ui_on_army_panel_recruit Army panel lower-right quadrant; sets mode 0x19; plays s021_02_wav / s021_01_wav
FUN_004424a3 0x004424a3 lotr2_game_ui_on_army_panel_trade Army panel upper-left; sets mode 0x14; calls trade prep helpers
FUN_004424d3 0x004424d3 lotr2_game_ui_on_army_panel_disband Army panel upper-right; sets mode 0x16
FUN_004424ea 0x004424ea lotr2_game_ui_on_army_panel_move Army panel lower-left; sets mode 0x15
FUN_00440df7 0x00440df7 lotr2_game_ui_detect_map_drag Mode 2 map drag; tracks mouse delta from DAT_00502a04/08; threshold 9 px
FUN_00440f4d 0x00440f4d lotr2_game_ui_on_mode_5_panel_click Mode 5 panel handler; calls FUN_0041a02d; returns 0/1/2 by DAT_00593440
FUN_004417fa 0x004417fa lotr2_game_ui_hit_test_minimap_province Minimap hit when DAT_005042c4; calls FUN_00441300; SP calls FUN_004418e5, MP sends opcode 0x26
FUN_004418e5 0x004418e5 lotr2_game_ui_apply_minimap_action Applies minimap province action for local player; loops FUN_00441974
FUN_00441b2d 0x00441b2d lotr2_game_ui_hit_test_build_action Build-toolbar hit when DAT_00505130; sets DAT_0055a374 build action index
FUN_00442501 0x00442501 lotr2_game_ui_on_end_turn_click Stores lotr2_game_turn_phase; SP calls FUN_00442548, MP sends opcode 0x21
FUN_00442548 0x00442548 lotr2_game_ui_apply_player_turn Writes turn phase to player record; calls economy/diplomacy tick chain for one player

Pass 28 — combat full rename sweep (0x4800000x4affff)#

See combat/MODULE.md. 219 FUN_* bodies and 15 figure/tile DAT_* field globals renamed in passes 27–36.

Apply source: tools/ghidra/combat_renames_pass27_36.py (imported by apply_anchor_renames.py).

Subsystem Address band Example new symbols
Pathfinding 0x481xxx0x484xxx lotr2_combat_run_pathfind_search, lotr2_combat_pathfind_to_tile
Battle UI / messages 0x484xxx0x489xxx lotr2_combat_dispatch_queued_message, lotr2_combat_siege_ui_action_id
Session lifecycle 0x48bxxx0x48exxx lotr2_combat_set_battle_outcome_code, lotr2_combat_load_siege_field_map
Spawn / formation 0x490xxx0x492xxx lotr2_combat_spawn_army_open_field, lotr2_combat_spawn_figure_batch
Figure state machine 0x494xxx0x496xxx lotr2_combat_tick_figure_start_melee, lotr2_combat_tick_figure_chase_target
Group AI / orders 0x499xxx0x49fxxx lotr2_combat_tick_all_groups, lotr2_combat_group_order_goto_siege_entry
Targeting / LOS / projectiles 0x4a4xxx0x4a6xxx lotr2_combat_scan_adjacent_melee_target, lotr2_combat_probe_los_square
Battle screen 0x4aexxx0x4afxxx lotr2_combat_tick_battle_screen, lotr2_combat_play_unit_strike_sound

Figure field globals renamed include lotr2_combat_figure_state (was DAT_00549571), lotr2_combat_figure_side, lotr2_combat_figure_tile_index, and battle-tile link/dirty bytes at 0x005841c20x005841c6.

Pass 24 candidates (superseded — applied in pass 24)#

Symbol Address New symbol Status
FUN_00438b90 0x00438b90 lotr2_game_screen_mode_tick Done
FUN_004d65fc 0x004d65fc lotr2_game_validate_scroll Done
FUN_0043a5af 0x0043a5af lotr2_game_pick_scroll_dir Done
FUN_0043a9ce 0x0043a9ce lotr2_game_ui_scroll_bar_hit Done
FUN_00456516 0x00456516 lotr2_game_economy_tick_player Done
FUN_00451511 0x00451511 lotr2_game_diplomacy_tick_player Done

Pass 28 — net sync helpers and payload globals#

Checksum helpers#

Old symbol Address New symbol Evidence
FUN_00448a29 0x00448a29 lotr2_net_set_speed_preset Sets DAT_0055c020, DAT_00573b9c, DAT_0059c040, lotr2_net_session_setup_state for presets 0/1/2; no xrefs in export (possibly dead)
FUN_00448cbd 0x00448cbd lotr2_net_buffer_checksum 8-bit additive sum from offset 0; variant of lotr2_net_checksum (which skips header bytes 0–3)
FUN_00448d0e 0x00448d0e lotr2_net_strided_checksum Nested loop: stride param_4, sum param_3 bytes per row across param_2 rows
FUN_00448d8e 0x00448d8e lotr2_net_partial_checksum Sum bytes [param_3 .. param_2); callee of lotr2_net_refresh_player_sync_checksums

Host sync orchestration#

Old symbol Address New symbol Evidence
FUN_00449729 0x00449729 lotr2_net_sync_stub_a Empty return; adjacent sync cluster no-op
FUN_00449734 0x00449734 lotr2_net_sync_stub_b Empty return; adjacent sync cluster no-op
FUN_0044973f 0x0044973f lotr2_net_host_resolve_sync_conflicts Walks DAT_00573bfc sync masks; compares checksum rows; sends opcode 0x10
FUN_00449ab4 0x00449ab4 lotr2_net_host_replay_sync_deltas Host-only; replays non-zero DAT_0059c3e0 entries; sends opcode 0x10
FUN_00449c22 0x00449c22 lotr2_net_sync_clear_battle_tiles Called from lotr2_net_pack/unpack_opcode_12; wraps lotr2_combat_clear_battle_tile_occupancy
FUN_00449c32 0x00449c32 lotr2_net_sync_stub_c Empty return
FUN_00449c3d 0x00449c3d lotr2_net_sync_apply_state_slice Copies state slice from sync tables; sends opcodes 0x50, 0x14, 0x13
FUN_00449d7c 0x00449d7c lotr2_net_sync_restore_state_slice Restores slice; sends opcode 0x0e; fatal via lotr2_net_on_fatal_error on overflow

Session helper#

Old symbol Address New symbol Evidence
FUN_004d2653 0x004d2653 lotr2_net_reset_send_state_ok Calls lotr2_net_reset_send_state() then returns 1

Payload frame globals#

Old symbol Address New symbol Evidence
DAT_0052d490 0x0052d490 lotr2_net_recv_frame Receive frame buffer; opcode indexes unpack table in dispatch
DAT_0052d491 0x0052d491 lotr2_net_recv_length Payload length byte; validated against DAT_004f0988[opcode]
DAT_0052d492 0x0052d492 lotr2_net_recv_checksum Received checksum byte
DAT_0052d493 0x0052d493 lotr2_net_recv_seq_flags Sequence + resend flags (low 6 bits seq; 0x40/0x80 resend)
DAT_0052d488 0x0052d488 lotr2_net_payload_write_ptr Payload write cursor; used by lotr2_net_payload_write
DAT_0052d460 0x0052d460 lotr2_net_payload_read_ptr Payload read cursor; used by lotr2_net_payload_read
DAT_0052d5a0 0x0052d5a0 lotr2_net_send_slots Send slot array base; stride 0x104 per slot

See net/MODULE.md, ../structs/lotr2_net_msg.md.

Deferred — orphan handler cluster (0x44ef1f0x44f598)#

34 function bodies at 0x0044ef1f0x0044f598 have no cross-references in this export. Likely orphaned Ghidra boundaries after Pass 20 collapsed tail handlers into duplicate lotr2_net_unpack_opcode_59 bodies. Do not rename until jump-table dump at 0x004f0820 is validated against the binary.

Pass 29 — game logic rename sweep (0x40650x458f)#

Apply source: tools/ghidra/game_renames_pass29.py (219 symbols; imported by apply_anchor_renames.py).

See game/MODULE.md.

Pass 29a — l2_eng text draw + UI line primitives (0x4070x408)#

Old symbol Address New symbol Evidence
FUN_0040780e 0x0040780e lotr2_game_ui_draw_eng_string Seek l2_eng string by sheet+index via lotr2_game_ui_eng_table_offset; draw via lotr2_game_ui_draw_text_run; 700+ call sites
FUN_00407a3b 0x00407a3b lotr2_game_ui_draw_number_field Formats int via lotr2_game_ui_int_to_ascii with prefix char (@, +, -); draws at screen coords
FUN_00407735 0x00407735 lotr2_game_ui_draw_eng_multiline Multi-line variant; calls lotr2_game_ui_draw_text_centered
FUN_00407cb4 0x00407cb4 lotr2_game_ui_draw_eng_wrapped Word-wrap l2_eng text into DAT_005d9ce0 rows; measures width via lotr2_game_ui_measure_text_width
FUN_0040710e 0x0040710e lotr2_game_ui_draw_text_run Walk byte string; # expands via lotr2_game_ui_eng_expand_hash; per-glyph blit via lotr2_game_ui_blit_font_glyph
FUN_004074eb 0x004074eb lotr2_game_ui_blit_font_glyph Lookup glyph in font sheet table DAT_004f23a0; clip + blit row
FUN_004084b4 0x004084b4 lotr2_game_ui_draw_line Bresenham line via lotr2_game_ui_plot_pixel
FUN_00408812 0x00408812 lotr2_game_ui_draw_panel_frame_style0 4-edge panel frame (colors 0x10/0x1f)

Pass 29b — UI widget toolkit (0x4130x416, 0x4d510x4d57)#

Widget descriptors are 0x18-byte records (12 × short): origin (x,y), tile index, size, callback pointer, type byte at +0xf (0x02 toggle, 0x04/0x05 action).

Old symbol Address New symbol Evidence
FUN_00413bf0 0x00413bf0 lotr2_game_ui_draw_status_text_rows Draws status-bar text rows from scroll list; marks dirty tiles
FUN_00413d65 0x00413d65 lotr2_game_ui_redraw_scroll_list Redraws bottom-panel scroll list; callee of frame render
FUN_00413f11 0x00413f11 lotr2_game_ui_begin_modal_overlay Saves palette; sets modal blit globals before overlay draw
FUN_00413f68 0x00413f68 lotr2_game_ui_end_modal_overlay Restores palette after modal overlay
FUN_00413fac 0x00413fac lotr2_game_ui_draw_modal_panel_grid Bordered tile grid sized from DAT_005d9c7c / DAT_005ec468
FUN_00414006 0x00414006 lotr2_game_ui_measure_menu_items Walks menu rows; sets width/height globals for dialog layout
FUN_00414102 0x00414102 lotr2_game_ui_clear_menu_slot_flags Clears 0x11-entry enable table at DAT_005ae7a0
FUN_0041413c 0x0041413c lotr2_game_ui_is_mode_in_table Returns 1 when screen mode appears in DAT_005bc6c0 table
FUN_0041418d 0x0041418d lotr2_game_ui_is_menu_item_enabled Tests menu slot flag in DAT_005ae7a0
FUN_004141bb 0x004141bb lotr2_game_ui_draw_menu_items Draws l2_eng menu rows with highlight/disable styles
FUN_00414339 0x00414339 lotr2_game_ui_draw_modal_frame_small Small modal panel + title via lotr2_gfx_draw_panel_style1
FUN_00414397 0x00414397 lotr2_game_ui_draw_modal_frame_large Large parameter dialog frame; number field + edge fill
FUN_00414548 0x00414548 lotr2_game_ui_draw_wait_backdrop Wait dialog tile grid + l2_eng status string
FUN_0041459b 0x0041459b lotr2_game_ui_store_widget_positions Copies widget-table origins into blit globals
FUN_00414611 0x00414611 lotr2_game_ui_draw_widget_table Walks N×0x18 widget descriptors; blits tiles; marks dirty
FUN_004147c9 0x004147c9 lotr2_game_ui_blit_tile_at Sets blit globals from tile table; calls lotr2_gfx_blit_tile16_block
FUN_0041487e 0x0041487e lotr2_game_ui_draw_sliders Draws slider track/thumb from min/max/value fields
FUN_00414a02 0x00414a02 lotr2_game_ui_hit_test_slider Hit-test slider decrement/track/increment zones
FUN_00414bad 0x00414bad lotr2_game_ui_slider_set_from_mouse Maps mouse X to slider value; marks dirty region
FUN_00414cba 0x00414cba lotr2_game_ui_slider_decrement Decrements bound value; invokes slider callback
FUN_00414dc5 0x00414dc5 lotr2_game_ui_slider_increment Increments bound value; invokes slider callback
FUN_00414ecc 0x00414ecc lotr2_game_ui_hit_test_icon_buttons Hit-test icon-button widget table
FUN_00414faf 0x00414faf lotr2_game_ui_clear_widget_pressed Clears press timers on widget table entries
FUN_00415021 0x00415021 lotr2_game_ui_handle_widget_click AABB hit-test + press timers; dispatches widget callbacks
FUN_00415377 0x00415377 lotr2_game_ui_handle_popup_menu Popup submenu input loop; row/column hit tests
FUN_004154af 0x004154af lotr2_game_ui_enter_popup_menu Saves screen mode; enters popup mode 0x32
FUN_00415542 0x00415542 lotr2_game_ui_dismiss_popup_menu Restores prior screen mode from saved value
FUN_004155ad 0x004155ad lotr2_game_ui_clear_popup_selection Clears popup highlight index
FUN_004155ea 0x004155ea lotr2_game_ui_hit_test_menu_rows Returns 1-based row under cursor in menu table
FUN_00415679 0x00415679 lotr2_game_ui_hit_test_menu_columns Column hit test for multi-column menus
FUN_0041570e 0x0041570e lotr2_game_ui_run_menu_dialog Modal menu dialog event loop (measure/draw/hit-test)
FUN_0041593b 0x0041593b lotr2_game_ui_hit_test_menu_row_y Row Y-band hit test helper for menus
FUN_004159ce 0x004159ce lotr2_game_ui_hit_test_widget_table Returns 1-based widget index under cursor
FUN_00415ba9 0x00415ba9 lotr2_game_ui_hit_test_rect_table Generic rect-table hit test (wizard config rows)
FUN_00415c42 0x00415c42 lotr2_game_ui_run_wait_dialog Blocking wait dialog with backdrop + message pump
FUN_00415cb4 0x00415cb4 lotr2_game_ui_enter_modal_mode Saves screen mode; enters mode 0x1e; draws modal frame
FUN_00415d23 0x00415d23 lotr2_game_ui_enter_parameter_dialog Saves screen mode; enters mode 0x21; large modal frame
FUN_00415da6 0x00415da6 lotr2_game_ui_hit_test_dialog_ok 0x18×0x18 OK hit rect when dialog flag set (pass 25)
FUN_00415dfd 0x00415dfd lotr2_game_ui_hit_test_ok_at Parameterized OK-button hit test at (param_1,param_2)
FUN_004d51a6 0x004d51a6 lotr2_game_ui_draw_screen_widgets Frame-render callee; switch(lotr2_game_screen_mode)lotr2_game_ui_draw_widget_table
FUN_004d57b4 0x004d57b4 lotr2_game_ui_handle_screen_widget_input First hit-test in lotr2_game_screen_mode_tick; per-mode widget click dispatch

Pass 29c — screen-mode hub + wizard + turn actions (0x43b0x43d)#

Old symbol Address New symbol Evidence
FUN_0043b316 0x0043b316 lotr2_game_wizard_on_start_step Wizard turn-phase dispatch; MP lobby start via lotr2_game_on_mp_lobby_start
FUN_0043b7f7 0x0043b7f7 lotr2_game_wizard_apply_config_choice Applies config via lotr2_game_wizard_set_config_value; MP sends net msg 9
FUN_0043c7d3 0x0043c7d3 lotr2_game_action_toggle_flag_b874 Toggles DAT_0059b874; follows pass-26 turn-action naming
FUN_0043ccf5 0x0043ccf5 lotr2_game_action_enter_diplomacy Mode 0x20; SP calls lotr2_game_diplomacy_init_sp, MP sends opcode 0x3b
FUN_0043d820 0x0043d820 lotr2_game_ui_hit_test_tax_slider Tax slider hit rect; calls lotr2_game_apply_tax_rate

Pass 29d — campaign UI blit + LZSS compress (0x40d0x413)#

Old symbol Address New symbol Evidence
FUN_00410f4c 0x00410f4c lotr2_game_ui_blit_ui_sprite Primary UI sprite draw from lotr2_ui_asset_scratch_ptr; 100+ call sites
FUN_0040dd4a 0x0040dd4a lotr2_game_ui_draw_map_entity_chain Walks entity linked list; positions by map facing
FUN_004130b8 0x004130b8 lotr2_game_save_compress_buffer LZSS compress for save blobs; init tree + sliding window
FUN_0041342d 0x0041342d lotr2_game_save_decompress_buffer LZSS decompress counterpart

Pass 29e — end-turn economy / diplomacy (0x4510x458)#

Old symbol Address New symbol Evidence
FUN_004513b0 0x004513b0 lotr2_game_end_turn_tick Season orchestrator; events, tax, morale, diplomacy chain
FUN_004514b0 0x004514b0 lotr2_game_end_turn_all_players Per-player loop calling lotr2_game_economy_tick_player + lotr2_game_diplomacy_tick_player
FUN_00451785 0x00451785 lotr2_game_apply_season_random_events Rotating event table; dispatches gold/food/population handlers
FUN_00452602 0x00452602 lotr2_game_apply_tax_income Per-player tax/income; updates map tile stamps
FUN_004578cf 0x004578cf lotr2_game_diplomacy_plan_slot Plans diplomacy slot spend; callee of lotr2_game_diplomacy_tick_player
FUN_00457c9f 0x00457c9f lotr2_game_allocate_prosperity Distributes prosperity across tax/army/farm/diplomacy buckets

Full symbol list: game_renames_pass29.py.

Pass 30 — eng string helpers, map army cells, CRT I/O#

Apply source: eng_renames_pass30.py, map_renames_pass30.py, io_renames_pass30.py (60 symbols).

Pass 30a — l2_eng string + percent math (0x4050x409)#

Old symbol Address New symbol Evidence
FUN_00405cd0 0x00405cd0 lotr2_game_ui_strstr_n Bounded substring search; CRT _str-style helper for l2_eng buffers
FUN_00405d55 0x00405d55 lotr2_game_ui_strchr_n Bounded strchr
FUN_00405daa 0x00405daa lotr2_game_ui_memcmp_n Bounded memcmp
FUN_00405e06 0x00405e06 lotr2_game_ui_memcpy_n Bounded memcpy
FUN_00405e46 0x00405e46 lotr2_game_ui_tolower_char ASCII lower-case single char
FUN_00405e80 0x00405e80 lotr2_game_ui_toupper_char ASCII upper-case single char
FUN_00405eba 0x00405eba lotr2_game_ui_strtolower In-place lower-case string
FUN_00405f16 0x00405f16 lotr2_game_ui_strtoupper In-place upper-case string
FUN_00405f72 0x00405f72 lotr2_game_ui_truncate_at_control Truncate at control/non-printable
FUN_00405fd3 0x00405fd3 lotr2_game_ui_str_delete_char Delete char by shifting left
FUN_00406003 0x00406003 lotr2_game_ui_str_insert_char Insert char by shifting right
FUN_00406034 0x00406034 lotr2_game_ui_str_trim_leading_space Trim leading spaces
FUN_0040608c 0x0040608c lotr2_game_ui_str_trim_trailing_space Trim trailing spaces
FUN_004060e5 0x004060e5 lotr2_game_ui_collapse_spaces Collapse duplicate spaces in buffer
FUN_004061c0 0x004061c0 lotr2_game_ui_measure_text_run Sum glyph widths via font table DAT_004f2380
FUN_00406289 0x00406289 lotr2_game_ui_measure_glyph_width Single-glyph width from font table
FUN_00406336 0x00406336 lotr2_game_ui_parse_decimal Parse ASCII digit run to int
FUN_004063c3 0x004063c3 lotr2_game_ui_seek_eng_nth_entry Seek nth l2_eng entry in sheet
FUN_00406492 0x00406492 lotr2_game_ui_copy_eng_substring Copy substring from l2_eng table
FUN_0040665a 0x0040665a lotr2_game_ui_update_text_cursor_limits Recompute text cursor bounds after edit
FUN_004066f6 0x004066f6 lotr2_game_ui_on_text_input_char Filter/append typed char to input buffer
FUN_00406915 0x00406915 lotr2_game_ui_text_input_backspace Backspace handler
FUN_004069fc 0x004069fc lotr2_game_ui_text_input_append Append byte to input buffer
FUN_00406c65 0x00406c65 lotr2_game_ui_measure_input_buffer_width Measure width of DAT_005efe40 buffer
FUN_00406cdf 0x00406cdf lotr2_game_ui_text_input_load_string Load C string into input buffer
FUN_00409720 0x00409720 lotr2_game_mul_percent (a*b)/100
FUN_0040974b 0x0040974b lotr2_game_mul_basis_points (a*b)/10000
FUN_00409776 0x00409776 lotr2_game_ratio_percent (a*100)/b with zero guard
FUN_004097b8 0x004097b8 lotr2_game_div_ceil Integer divide with ceiling

Pass 30b — map province army / build queue (0x7470x7d2)#

Old symbol Address New symbol Evidence
FUN_00474720 0x00474720 lotr2_map_clear_province_army_record Zeroes 0x1a4-byte province army via lotr2_combat_zero_figure_bytes
FUN_00474aad 0x00474aad lotr2_map_release_army_at_cell Calls lotr2_combat_release_province_army
FUN_00474e49 0x00474e49 lotr2_map_resolve_army_cell_interaction Army-on-army tile interaction; battle messages
FUN_004752b0 0x004752b0 lotr2_map_tick_province_army_move Campaign army step; pathfind + resource transfer
FUN_00475c8f 0x00475c8f lotr2_map_clear_army_cells_in_rect Clears army cells via lotr2_map_clear_cell_with_upkeep
FUN_004762d7 0x004762d7 lotr2_map_relocate_army_tile_link Link/unlink province army tile occupancy
FUN_004766e9 0x004766e9 lotr2_map_pathfind_province_army Pathfind search for province army record
FUN_004798bd 0x004798bd lotr2_map_display_next_army_slot Cycle army slot index; lotr2_map_set_cell_display
FUN_004799ba 0x004799ba lotr2_map_display_army_slot_tile Display army slot with tile type param
FUN_0047a1d1 0x0047a1d1 lotr2_map_claim_province_rect Claim rectangular province cell region
FUN_0047a356 0x0047a356 lotr2_map_try_claim_cell Try claim single map cell
FUN_0047a44a 0x0047a44a lotr2_map_try_claim_2x2_block Try claim 2×2 map block
FUN_0047ac3d 0x0047ac3d lotr2_map_mark_province_rect_dirty Mark rect cells dirty (facing-adjusted)
FUN_0047ad96 0x0047ad96 lotr2_map_init_edge_visibility Init edge visibility counters from province tables
FUN_0047b1b9 0x0047b1b9 lotr2_map_update_visibility_north North-edge visibility update
FUN_0047b5ac 0x0047b5ac lotr2_map_update_visibility_east East-edge visibility update
FUN_0047ba97 0x0047ba97 lotr2_map_update_visibility_south South-edge visibility update
FUN_0047c1b0 0x0047c1b0 lotr2_map_advance_build_queue_slot Advance build-queue slot index
FUN_0047c2de 0x0047c2de lotr2_map_reset_build_queue_slots Reset build-queue slot bytes
FUN_0047c317 0x0047c317 lotr2_map_toggle_player_slot_flags Toggle 16 player slot flags
FUN_0047c375 0x0047c375 lotr2_map_paint_build_queue_rect Paint build-queue rect on overlay grid
FUN_0047c6ce 0x0047c6ce lotr2_map_clear_build_queue_layer Clear build-queue layer byte
FUN_0047c784 0x0047c784 lotr2_map_set_build_queue_tile Set build-queue tile pair
FUN_0047c956 0x0047c956 lotr2_map_stamp_build_queue_tile Stamp build-queue tile with params
FUN_0047cb82 0x0047cb82 lotr2_map_place_structure_cell Place structure on single cell
FUN_0047ccc5 0x0047ccc5 lotr2_map_try_place_structure_rect Try place structure rect
FUN_0047ce33 0x0047ce33 lotr2_map_cell_distance_manhattan Manhattan distance between cells
FUN_0047ce8f 0x0047ce8f lotr2_map_find_nearest_cell_flag Nearest cell matching flag search
FUN_0047d2ac 0x0047d2ac lotr2_map_clear_province_layer_by_index Clears layer via lotr2_map_clear_province_layers

Pass 31 — map army path + grid helpers (0x7480x7fb4)#

Old symbol Address New symbol Evidence
FUN_00474815 0x00474815 lotr2_map_reset_army_move_counters Zeros per-province move counters at end of turn
FUN_00474870 0x00474870 lotr2_map_army_handler_nop Army-type vtable stub
FUN_0047487b 0x0047487b lotr2_map_army_handler_tick_move Type-1 handler; sets sprite dir; calls lotr2_map_tick_province_army_move
FUN_00474c14 0x00474c14 lotr2_map_army_handler_merge_arrive Arrival state 10; merge sprite setup
FUN_00474d1e 0x00474d1e lotr2_map_army_handler_trade_arrive Trade arrival handler (same tile pattern as merge)
FUN_00474e28 0x00474e28 lotr2_map_army_handler_stub_0 Vtable stub
FUN_00474e33 0x00474e33 lotr2_map_army_handler_stub_1 Vtable stub
FUN_00474e3e 0x00474e3e lotr2_map_army_handler_stub_2 Vtable stub
FUN_0047581c 0x0047581c lotr2_map_army_sprite_offset_for_dir Direction + terrain → sprite char offset
FUN_004758a0 0x004758a0 lotr2_map_advance_army_path_step One path step; calls probe/classify/relocate
FUN_00475de6 0x00475de6 lotr2_map_probe_army_step_direction Probe offset cell for direction 0–7
FUN_0047618f 0x0047618f lotr2_map_classify_army_target_cell Target tile interaction code
FUN_0047688f 0x0047688f lotr2_map_find_path_radius_to_cell Expanding radius pathfind helper
FUN_0047690b 0x0047690b lotr2_map_find_nearest_hostile_army Hostile army search by distance
FUN_00476a85 0x00476a85 lotr2_map_find_nearest_friendly_army Friendly army search (owner byte match)
FUN_0047a662 0x0047a662 lotr2_map_try_claim_3x3_block Claim 3×3 structure footprint
FUN_0047a899 0x0047a899 lotr2_map_try_claim_4x4_block Claim 4×4 structure footprint
FUN_0047bf52 0x0047bf52 lotr2_map_cache_neighbor_province_ids Cache N/E/S/W province ids at cursor
FUN_0047c019 0x0047c019 lotr2_map_get_neighbor_edge_flags Edge cell flags for neighbor scan
FUN_0047c58c 0x0047c58c lotr2_map_clear_cell_occupancy_bits Clear bit 0x40 on 8×64 cell strip
FUN_0047d002 0x0047d002 lotr2_map_rect_has_passable_cell Rect: any empty passable cell
FUN_0047d175 0x0047d175 lotr2_map_rect_is_unoccupied Rect: all cells empty
FUN_0047d2f3 0x0047d2f3 lotr2_map_nop_stub No-op placeholder
FUN_0047d2fe 0x0047d2fe lotr2_map_find_strongest_army_near_capital Strongest army in 5×5 around capital
FUN_0047d4d0 0x0047d4d0 lotr2_map_read_selected_cell Read clicked cell into selection globals
FUN_0047d8ac 0x0047d8ac lotr2_map_clear_army_slot_marker Clear build-queue marker for cell
FUN_0047dcd7 0x0047dcd7 lotr2_map_compute_neighbor_visibility 8-neighbor visibility bitmask
FUN_0047dd66 0x0047dd66 lotr2_map_is_visible_overlay_cell Overlay grid visibility test
FUN_0047dea7 0x0047dea7 lotr2_map_highlight_province_cells Highlight all cells for province id
FUN_0047df39 0x0047df39 lotr2_map_highlight_rect_cells Highlight rectangular region
FUN_0047fb40 0x0047fb40 lotr2_map_spawn_province_army_at_cell Spawn province army on empty cell
FUN_0047fe58 0x0047fe58 lotr2_combat_spawn_figure_at_map_cell Alloc combat figure from map placement UI

See map/MODULE.md. Rename script: map_renames_pass30.py.

Pass 30c — CRT lowio (0x4e4d0x4e6e)#

Old symbol Address New symbol Evidence
FUN_004e4da0 0x004e4da0 crt_write MSVC _write lowio; WriteFile path; used by save write
FUN_004e6e40 0x004e6e40 crt_close CRT handle close after save/load I/O

See io/MODULE.md, save/MODULE.md.

Pass 31a — audio preloaded SFX + stream refill (0x42fe0x430f)#

Old symbol Address New symbol Evidence
FUN_0042feb5 0x0042feb5 lotr2_audio_shutdown_directsound Stop streams, release preloaded slots, Release lotr2_audio_lpds
FUN_0042ff6d 0x0042ff6d lotr2_audio_init_primary_waveformat Seeds WAVEFORMATEX at DAT_005310f0 (44.1 kHz stereo PCM)
FUN_0042ffcb 0x0042ffcb lotr2_audio_preload_wav_bank Loads path table into preloaded secondary-buffer slots
FUN_004302a0 0x004302a0 lotr2_audio_play_preloaded GetStatus + Play on preloaded slot (DAT_00530f5c array)
FUN_00430396 0x00430396 lotr2_audio_restart_preloaded Stop + Play on preloaded slot
FUN_0043044f 0x0043044f lotr2_audio_play_preloaded_slot Thin wrapper calling lotr2_audio_play_preloaded
FUN_0043046b 0x0043046b lotr2_audio_release_preloaded Stop + Release preloaded slot buffer
FUN_004304e0 0x004304e0 lotr2_audio_stop_preloaded Stop preloaded slot (no release)
FUN_0043062c 0x0043062c lotr2_audio_stream_channel_enabled Gates stream playback on enable flags + buffer presence
FUN_004306a9 0x004306a9 lotr2_audio_noop Empty stub; placeholder in init failure path
FUN_00430f55 0x00430f55 lotr2_audio_stream_refill Refills streaming buffer from MMIO WAV data

See audio/MODULE.md.

Pass 31b — CRT lowio helpers (0x4e7b0x4e81)#

Old symbol Address New symbol Evidence
FUN_004e7b50 0x004e7b50 crt_file_length __lseek tell/end/restore on CRT handle table
FUN_004e7c10 0x004e7c10 crt_set_current_drive SetCurrentDirectoryA + SetEnvironmentVariableA (=X:)
FUN_004e7cf0 0x004e7cf0 crt_chsize MSVC _chsize; truncates file via SetEndOfFile
FUN_004e81b0 0x004e81b0 crt_stack_probe MSVC stack allocation probe before large frames

See io/MODULE.md.

Pass 31c — DirectPlay dialog globals + LAB aliases#

Old symbol Address New symbol Evidence
LAB_00403053 0x00403053 lotr2_net_enum_sp_callback DirectPlayEnumerate callback in SP picker dialog
LAB_0040209f 0x0040209f lotr2_net_enum_sessions_callback EnumSessions callback in browse dialog
DAT_00502a78 0x00502a78 lotr2_net_dlg_sp_list_hwnd SP listbox HWND from GetDlgItem(0x3e9)
DAT_00502a84 0x00502a84 lotr2_net_dlg_sp_sel_index Selected SP list index (LB_GETCURSEL)
DAT_00502a70 0x00502a70 lotr2_net_dlg_session_name_hwnd Session-name edit HWND (GetDlgItem(1000))
DAT_00502a7c 0x00502a7c lotr2_net_dlg_browse_list_hwnd Browse-sessions list HWND (GetDlgItem(0x400))

See net/MODULE.md.

Pass 33 — game text input, RNG, map blit, castle overview#

Apply source: tools/ghidra/game_renames_pass33.py (43 symbols).

See game/MODULE.md.

Pass 33a — text input cursor / edit (0x40690x406c)#

Old symbol Address New symbol Evidence
FUN_00406931 0x00406931 lotr2_game_ui_text_input_on_return WM_KEYDOWN 0x0d; sets selection max DAT_005bc614
FUN_00406946 0x00406946 lotr2_game_ui_text_input_on_backspace WM_KEYDOWN 0x08; cursor left + delete char
FUN_00406969 0x00406969 lotr2_game_ui_text_input_on_delete_key WM_KEYDOWN 0x2e; delete at cursor
FUN_00406979 0x00406979 lotr2_game_ui_text_input_toggle_insert_mode WM_KEYDOWN 0x2d; toggles DAT_005d9c54
FUN_00406992 0x00406992 lotr2_game_ui_text_input_cursor_left WM_KEYDOWN 0x25
FUN_004069b0 0x004069b0 lotr2_game_ui_text_input_cursor_right WM_KEYDOWN 0x27
FUN_004069d2 0x004069d2 lotr2_game_ui_text_input_cursor_home WM_KEYDOWN 0x24
FUN_004069e7 0x004069e7 lotr2_game_ui_text_input_cursor_end WM_KEYDOWN 0x23; cursor = DAT_005d9c50
FUN_00406a9e 0x00406a9e lotr2_game_ui_text_input_delete_char_at_cursor str_delete_char on DAT_005efe40 buffer
FUN_00406ade 0x00406ade lotr2_game_ui_copy_input_buffer 2000-byte buffer copy
FUN_00406b1f 0x00406b1f lotr2_game_ui_text_input_validate_decimal Decimal-point validation state _DAT_005ec474
FUN_00406ba6 0x00406ba6 lotr2_game_ui_text_input_strip_spaces Strip spaces from input buffer
FUN_00406c1f 0x00406c1f lotr2_game_ui_text_input_update_length Recompute DAT_005d9c50; callee of lotr2_game_sim_tick

Pass 33b — frame counters, RNG, distance (0x40920x4099)#

Old symbol Address New symbol Evidence
FUN_004092c2 0x004092c2 lotr2_game_ui_advance_frame_counters Increments blink/animation globals (DAT_005efe20, etc.)
FUN_004093fb 0x004093fb lotr2_game_rng_lfsr_shift_wide_pair 31-bit LFSR on DAT_005da4b8 / DAT_005da4bc
FUN_004094e1 0x004094e1 lotr2_game_rng_lfsr_shift_byte 31-bit LFSR on DAT_005bc76c
FUN_0040954e 0x0040954e lotr2_game_rng_bounded Masked random ≤ param via LFSR refresh
FUN_00409800 0x00409800 lotr2_game_lookup_threshold Sorted [threshold,value] table lookup
FUN_00409862 0x00409862 lotr2_game_dist_manhattan Sum of |Δx|+|Δy|; combat/map pathfinding
FUN_00409901 0x00409901 lotr2_game_dist_chebyshev max(|Δx|,|Δy|)
FUN_004099b5 0x004099b5 lotr2_game_dist_axis_min min(|Δx|,|Δy|)

Pass 33c — campaign map entity draw (0x40a90x40b8)#

Old symbol Address New symbol Evidence
FUN_0040a9d0 0x0040a9d0 lotr2_game_ui_campaign_map_redraw_tick Per-frame campaign map draw; calls layered + simple passes
FUN_0040ab7f 0x0040ab7f lotr2_game_ui_draw_map_entities_layered Full entity layer with stack counts and badges
FUN_0040ad98 0x0040ad98 lotr2_game_ui_draw_map_entities_simple Entity chain blit without building badges
FUN_0040af13 0x0040af13 lotr2_game_ui_draw_map_entities_with_badges Entity + building badge pass
FUN_0040b173 0x0040b173 lotr2_game_ui_draw_map_column_left Left-edge column entity draw
FUN_0040b2bf 0x0040b2bf lotr2_game_ui_draw_map_column_from_sel Column draw from selected province
FUN_0040b7c5 0x0040b7c5 lotr2_game_ui_draw_map_row_with_stacks Row pass with stack-count overlay
FUN_0040b8bd 0x0040b8bd lotr2_game_ui_draw_map_sel_column_stacks Selected-column row with stacks
FUN_00411586 0x00411586 lotr2_game_ui_nop Empty stub

Pass 46 — map entity draw tail + text-input slot I/O (0x406d0x40ca, 0x45d4)#

Completes pass 33c gaps: column interior/bridge passes, stamp/clip dispatch, stack-icon blit, and inline PL8 row stamp helpers called from lotr2_game_ui_prep_map_entity_stamp.

Old symbol Address New symbol Evidence
FUN_00406d84 0x00406d84 lotr2_game_ui_copy_input_buffer_out Copies DAT_005efe40 text buffer to caller buffer
FUN_00406dcb 0x00406dcb lotr2_game_ui_text_input_load_from_slot lotr2_asset_read_file into input buffer; slot index param
FUN_00406e74 0x00406e74 lotr2_game_ui_text_input_save_to_slot Pads gaps with spaces; lotr2_asset_write_file_at
FUN_00408f6e 0x00408f6e lotr2_gfx_blit_sprite_clipped Sets blit globals; lotr2_gfx_blit_clip_x/y + row blit
FUN_0040b3f9 0x0040b3f9 lotr2_game_ui_draw_map_column_interior_row Column interior cells; callee of layered draw
FUN_0040b53f 0x0040b53f lotr2_game_ui_draw_map_column_bridge_row Selected-column bridge row (pass types 0/3/4)
FUN_0040baae 0x0040baae lotr2_game_ui_draw_map_column_clip_bridge Clip-blitz bridge row via lotr2_game_ui_prep_map_entity_clip_blit
FUN_0040bc0c 0x0040bc0c lotr2_game_ui_draw_map_column_clip_interior Clip-blitz interior column row
FUN_0040bcd3 0x0040bcd3 lotr2_game_ui_prep_map_entity_stamp Entity metadata + stamp/clip dispatch by pass type
FUN_0040bf85 0x0040bf85 lotr2_game_ui_stamp_map_entity_pl8 PL8 stamp router; lotr2_gfx_stamp_pl8_* by facing/type
FUN_0040c4cc 0x0040c4cc lotr2_game_ui_prep_map_entity_clip_blit Clip-blitz path; lotr2_gfx_blit_map_sprite_*_clip
FUN_0040cab2 0x0040cab2 lotr2_game_ui_blit_entity_stack_icon Stack-icon sprite; flag 0x80 on entity; param 0/1/2 column edge
FUN_0040f620 0x0040f620 lotr2_game_ui_nop_dev_stub_a Empty stub near dev save hook
FUN_0040f62b 0x0040f62b lotr2_game_ui_nop_dev_stub_b Empty stub near dev save hook
FUN_0041c1a3 0x0041c1a3 lotr2_game_ui_nop_player_redraw_hook Empty stub in player-change full redraw
FUN_0045d460 0x0045d460 lotr2_gfx_stamp_map_entity_stride282 Unrolled stride-0x282 row stamp; callee of prep/stamp
FUN_0045dfbb 0x0045dfbb lotr2_gfx_stamp_map_entity_stride280 Stride-0x280 edge stamp; pass type 3
FUN_0045e536 0x0045e536 lotr2_gfx_stamp_map_entity_stride282_edge Stride-0x282 trailing-edge stamp; pass type 4
FUN_0045eab1 0x0045eab1 lotr2_gfx_stamp_map_entity_rows_compact Compact row stamp; callee of lotr2_game_ui_stamp_map_entity_pl8

Pass 33d — castle overview + mode 5 panel (0x417e0x41a6)#

Old symbol Address New symbol Evidence
FUN_00417e20 0x00417e20 lotr2_game_ui_build_overview_row_list Builds DAT_0055a870 / DAT_00582d00 row type arrays
FUN_0041800e 0x0041800e lotr2_game_ui_draw_overview_farm_row Overview row type 1; food production stats
FUN_00418199 0x00418199 lotr2_game_ui_draw_overview_lumber_row Overview row type 0; lumber stats
FUN_00418324 0x00418324 lotr2_game_ui_draw_overview_quarry_row Overview row type 2; stone stats
FUN_00418461 0x00418461 lotr2_game_ui_draw_overview_iron_row Building slot type 4
FUN_004184f7 0x004184f7 lotr2_game_ui_draw_overview_gold_row Building slot type 5
FUN_0041858d 0x0041858d lotr2_game_ui_draw_overview_cattle_row Building slot type 6
FUN_00418623 0x00418623 lotr2_game_ui_draw_overview_fort_row Building slot type 7
FUN_00418730 0x00418730 lotr2_game_ui_draw_overview_church_row Building slot type 3; l2_eng labels
FUN_0041a02d 0x0041a02d lotr2_game_ui_setup_mode5_panel Mode 5 overlay panel init; hub callee
FUN_0041a5b3 0x0041a5b3 lotr2_game_ui_draw_mode5_building_icons Draw 8× building icon columns
FUN_0041a616 0x0041a616 lotr2_game_ui_draw_mode5_icon_column Single column of castle building sprites

Pass 31d — screen-mode dialog draw / teardown (0x4170x41f)#

Apply after pass 33 in apply_anchor_renames.py so overview/mode-5 symbols above are not overwritten.

Old symbol Address New symbol Evidence
FUN_00417150 0x00417150 lotr2_game_ui_on_screen_phase_exit Called when lotr2_game_screen_phase clears; switch on lotr2_game_screen_mode
FUN_0041755f 0x0041755f lotr2_game_ui_enter_campaign_map_mode Mode 0 init; status sprites + lotr2_game_ui_redraw_province_panel
FUN_00417735 0x00417735 lotr2_game_ui_redraw_province_panel Province panel text/stats; calls overview row drawers
FUN_00418a08 0x00418a08 lotr2_game_ui_draw_province_minimap 0x80×0x80 minimap blit in panel
FUN_00418c1c 0x00418c1c lotr2_game_ui_paint_minimap_pixels Pixel plot loop for minimap modes
FUN_00418ffe 0x00418ffe lotr2_game_ui_draw_trade_dialog Mode 0x14; l2_eng sheet 0x49
FUN_0041947c 0x0041947c lotr2_game_ui_draw_move_army_dialog Mode 0x15; sheet 0x56
FUN_00419648 0x00419648 lotr2_game_ui_draw_disband_dialog Mode 0x16; sheet 0x55
FUN_00419abf 0x00419abf lotr2_game_ui_draw_recruit_dialog Mode 0x19; sheet 0x57
FUN_0041c77d 0x0041c77d lotr2_game_ui_draw_save_wizard_chrome Modes '5'/'6' save/load wizard frame
FUN_0041c950 0x0041c950 lotr2_game_ui_draw_save_slot_list Save slot rows inside wizard
FUN_0041cd6c 0x0041cd6c lotr2_game_ui_draw_options_dialog Mode '9'; sheet 0x32
FUN_0041ddbd 0x0041ddbd lotr2_game_ui_enter_merchant_screen Mode 0x08; loads merchant.pl8
FUN_0041fcc1 0x0041fcc1 lotr2_game_ui_enter_armoury_screen Mode 0x0a; loads armoury.pl8

Full list: game_ui_dialog_renames_pass31.py (62 symbols; excludes pass-33 overview/mode-5 overlap).

Notes#

  • thunk_FUN_* symbols become thunk_<newname> automatically when the embedded FUN_* token is replaced.
  • LAB_0040209a (0x40209a) is the registered WndProc pointer; decompiled body at lotr2_ui_wndproc_impl (0x4cd0a4) may be a Ghidra address split — verify on re-export.
  • Pass 20 renamed all app-message pack/unpack handlers in the 0x449e cluster; opcodes 8–9 remain TBD in the handler layout (may alias other table slots).
  • Pass 28 deferred the orphan cluster at 0x44ef1f0x44f598 (see above).
  • Global replace created duplicate function bodies for some handlers (e.g. lotr2_net_payload_write ×261); dedup requires Ghidra re-export or a dedicated script — not addressed in pass 28.
  • DirectPlay imports were hidden as Ordinal_1 (DirectPlayCreate) and Ordinal_2 (DirectPlayEnumerate) from DPLAYX.DLL, which is why the earlier by-name DirectPlay* search missed them. See net/MODULE.md, ../protocols/dplay.md, and ../structs/lotr2_net_msg.md.
  • s_Lords2_Session1 is the default DPSESSIONDESC2 session name used by the host path in lotr2_net_setup_session.

Pass 32 — asset path helpers + UI shell (0x4c9f0x4cce)#

Rename script: asset_ui_renames_pass32.py.

Pass 32a — asset I/O extensions#

Old symbol Address New symbol Evidence
FUN_004c9f84 0x004c9f84 lotr2_asset_probe_readable lotr2_io_open + CD fallback; returns 0/1/2 without reading payload
FUN_004ca199 0x004ca199 lotr2_asset_write_file lotr2_io_open (0x8301) + crt_write + crt_close
FUN_004cac46 0x004cac46 lotr2_asset_write_file_at Seek + write variant (0x8101)
FUN_004caccf 0x004caccf lotr2_asset_read_ini_key_byte Reads 1000 bytes, scans for marker, returns byte at offset 7

Pass 32b — status.txt / diverged.txt debug I/O#

Old symbol Address New symbol Evidence
FUN_004cabdf 0x004cabdf lotr2_ui_status_timestamp _asctime into 0x28-byte prefix buffer (DAT_00507570)
FUN_004ca57d 0x004ca57d lotr2_ui_flush_status_txt Appends DAT_00505140 to status.txt (create vs append modes)
FUN_004ca630 0x004ca630 lotr2_ui_format_diverge_record Serializes game-state tables into text for diverged.txt
FUN_004caaee 0x004caaee lotr2_ui_write_diverge_txt Opens diverged.txt when DAT_00593448 set; calls format helper

Pass 32c — palette fade + backbuf presentation#

Old symbol Address New symbol Evidence
FUN_004cb033 0x004cb033 lotr2_gfx_palette_shift_entry Shifts DD palette RGB triple; lotr2_gfx_update_dd_palette
FUN_004cb0fa 0x004cb0fa lotr2_gfx_palette_adjust_index Bumps palette index with clamp/wrap
FUN_004cb1b2 0x004cb1b2 lotr2_gfx_palette_toggle_reserved0 Toggles index 0 between 0 and 0x3f
FUN_004cb1ee 0x004cb1ee lotr2_gfx_palette_noop Empty stub called from palette refresh paths
FUN_004cb3f8 0x004cb3f8 lotr2_gfx_begin_palette_fade Copies target palette; sets screen mode 0x23 ('#')
FUN_004cb532 0x004cb532 lotr2_gfx_fade_arm Sets DAT_00505350 fade counter
FUN_004cb547 0x004cb547 lotr2_gfx_fade_step Interpolates palette entries 10..0xf5; restores prior screen mode
FUN_004cb8b2 0x004cb8b2 lotr2_gfx_load_256_palette lotr2_asset_read_file 0x300 bytes + lotr2_gfx_apply_palette_rgb
FUN_004cb8e2 0x004cb8e2 lotr2_gfx_load_256_palette_b Duplicate load path (same callees)
FUN_004cb912 0x004cb912 lotr2_gfx_restore_palette_present Apply buffer palette + clear backbuf + fullscreen refresh
FUN_004cb934 0x004cb934 lotr2_gfx_apply_buffer_palette lotr2_gfx_apply_palette_rgb(0x507250) only
FUN_004cb94c 0x004cb94c lotr2_gfx_present_backbuf_tiled 16×16 Blt grid from backbuf surface to primary
FUN_004cba06 0x004cba06 lotr2_gfx_flip_full_surface Single full-surface Blt
FUN_004cba3f 0x004cba3f lotr2_gfx_stub_present_ok Returns 1 (present hook placeholder)
FUN_004cba54 0x004cba54 lotr2_gfx_dim_backbuf_full Remaps all 0x4b000 pixels through dim lookup table
FUN_004cbb31 0x004cbb31 lotr2_gfx_dim_backbuf_rect Rectangular dim variant
FUN_004cbc43 0x004cbc43 lotr2_gfx_remap_backbuf_palette Reserved-index nearest-color remap (full screen)
FUN_004cbfab 0x004cbfab lotr2_gfx_clear_backbuf memset 0x4b000 bytes on lotr2_gfx_backbuf_pixels
FUN_004cbfdb 0x004cbfdb lotr2_gfx_present_noop Empty present-hook stub
FUN_004cbfe6 0x004cbfe6 lotr2_gfx_stub_ret1 Returns 1
FUN_004cbffb 0x004cbffb lotr2_ui_idle_noop Empty idle-hook stub

Pass 32d — Win32 pointer / cursor / scratch buffer#

Old symbol Address New symbol Evidence
FUN_004cc027 0x004cc027 lotr2_ui_clear_click_hold Clears DAT_0050759c click-hold flag
FUN_004cc03c 0x004cc03c lotr2_ui_post_synthetic_mousemove PostMessageA(hwnd, 0x200, x, y)
FUN_004cc062 0x004cc062 lotr2_ui_poll_pointer_state GetCursorPos; maps to backbuf coords; button edge detect
FUN_004cc437 0x004cc437 lotr2_ui_set_cursor_theme SetCursor by theme id (arrow/hand/etc.)
FUN_004cc524 0x004cc524 lotr2_ui_yield_hook Heavily called cooperative-yield stub (empty body)
FUN_004cc52f 0x004cc52f lotr2_ui_hit_test_point Point-in-rect vs DAT_005042cc/d0
FUN_004cc58b 0x004cc58b lotr2_ui_pump_messages_once Clears wait flags; sets DAT_00507a64
FUN_004cc5bc 0x004cc5bc lotr2_ui_wait_ready_loop Spin until DAT_00507a64 cleared
FUN_004cc5e0 0x004cc5e0 lotr2_ui_drain_message_queue Busy-wait message pump
FUN_004cc60b 0x004cc60b lotr2_ui_capture_click_row Records click Y when LMB down inside rect
FUN_004cc68e 0x004cc68e lotr2_ui_block_until_button_up Poll loop until RMB/LMB release flags
FUN_004cc730 0x004cc730 lotr2_ui_block_until_button_up_timeout Timed variant; returns 1 on release
FUN_004cc7e9 0x004cc7e9 lotr2_ui_tick_delta_ms timeGetTime delta clamped to ≥30 ms
FUN_004cc82d 0x004cc82d lotr2_ui_debounce_elapsed_a Interval debounce using DAT_00502a58
FUN_004cc873 0x004cc873 lotr2_ui_debounce_elapsed_b Interval debounce using DAT_00502a5c
FUN_004cc8ec 0x004cc8ec lotr2_ui_spin_delay_a Counted calls to lotr2_ui_noop_8d6
FUN_004cc90e 0x004cc90e lotr2_ui_spin_delay_b Counted calls to lotr2_ui_noop_8e1
FUN_004cc930 0x004cc930 lotr2_ui_spin_delay_combo Bundled delay sequence
FUN_004ccc71 0x004ccc71 lotr2_ui_query_free_phys_mem GlobalMemoryStatus; returns dwAvailPhys
FUN_004cccac 0x004cccac lotr2_ui_resize_scratch_buffer Realloc lotr2_ui_asset_scratch_ptr asset scratch (DAT_00507a8c)
FUN_004cccf8 0x004cccf8 lotr2_ui_free_scratch_buffer Frees scratch via FUN_004dc110
FUN_004ccd32 0x004ccd32 lotr2_ui_show_load_phase_msgs Three lotr2_ui_show_loading_msg progress strings
FUN_004ccdde 0x004ccdde lotr2_ui_on_app_foreground Foreground check + loading message when regaining focus

See asset/MODULE.md, ui/MODULE.md.

Pass 34 — turn sim / campaign AI (0x4b00000x4bffff)#

Rename script: game_renames_pass34.py (97 symbols).

Player record stride 0x160 (lotr2_game_player_active…); army record stride 0x1a4 (lotr2_game_army_record_table…). Outer turn phase lotr2_game_ai_turn_phase (1–7); inner AI step lotr2_game_ai_player_step[player] (0–13, 999=done).

Pass 34a — Phase dispatcher & turn state#

Old symbol Address New symbol Evidence
FUN_004b0980 0x004b0980 lotr2_game_ai_turn_phase_tick Sim-tick driver; switches on lotr2_game_ai_turn_phase; phase 7 → lotr2_game_end_turn_tick
FUN_004b30a9 0x004b30a9 lotr2_game_ai_advance_turn_phase Bumps phase 1–7; calls lotr2_game_ai_reset_step_counters
FUN_004b1c17 0x004b1c17 lotr2_game_ai_reset_step_counters Zeros lotr2_game_ai_player_step[]; dead players → 999
FUN_004b1ca6 0x004b1ca6 lotr2_game_ai_all_steps_complete Returns whether any active player has step < 999
FUN_004b2bed 0x004b2bed lotr2_game_ai_turn_state_init New-game AI state init; sets phase 1
FUN_004b2c8a 0x004b2c8a lotr2_game_ai_init_unit_type_bitmasks Sets five unit-type bitmask globals
FUN_004b2cb8 0x004b2cb8 lotr2_game_ai_screen_mode_matches Compares expected screen mode byte
FUN_004b2d02 0x004b2d02 lotr2_game_ai_assign_nation_culture_slots Assigns culture slots for empty players
FUN_004b1ff1 0x004b1ff1 lotr2_game_ai_init_new_game_players Resets player records; assigns capitals from slot pairs
FUN_004b1eb7 0x004b1eb7 lotr2_game_ai_sort_province_slot_pairs Bubble-sorts 6 entries at DAT_0055ac00
FUN_004b1d41 0x004b1d41 lotr2_game_ai_mark_player_defeated Sets defeated flag; records elimination rank
FUN_004b1df5 0x004b1df5 lotr2_game_ai_clear_player_human_flag Clears human/defeated flags on player record

Pass 34b — AI player step loop (14 steps)#

Old symbol Address New symbol Step Evidence
FUN_004b0cde 0x004b0cde lotr2_game_ai_player_step_loop Rotates DAT_0055a84c; 14-way switch on lotr2_game_ai_player_step
FUN_004b10c1 0x004b10c1 lotr2_game_ai_downgrade_inactive_garrisons First callee of lotr2_game_end_turn_tick for AI players
FUN_004b113f 0x004b113f lotr2_game_ai_compute_player_rankings 7 Sorts players by score; sets ranking globals
FUN_004b199a 0x004b199a lotr2_game_ai_update_player_alive_status 0 Counts provinces/armies; elimination messages
FUN_004b342b 0x004b342b lotr2_game_ai_aggregate_player_province_stats 0,13 Averages prosperity/population across owned tiles
FUN_004b86e5 0x004b86e5 lotr2_game_ai_process_diplomacy_queue 1 Drains 5-slot queue DAT_0059c230
FUN_004b6bc4 0x004b6bc4 lotr2_game_ai_diplomacy_relation_tick 2 Ally/war attitude; propose/break alliance
FUN_004b38c3 0x004b38c3 lotr2_game_ai_score_build_priorities 3 Sets build tier from culture + prosperity
FUN_004b444b 0x004b444b lotr2_game_ai_set_troop_recruitment_targets 4 Troop goals from castle count
FUN_004b3f8c 0x004b3f8c lotr2_game_ai_build_recruit_pass 5 Downgrade garrisons; pick build template
FUN_004b5057 0x004b5057 lotr2_game_ai_province_structure_build 6 Builds when pop/gold thresholds met
FUN_004b5bcf 0x004b5bcf lotr2_game_ai_military_composite_pass 7 Siege + attack province picks
FUN_004b5bfe 0x004b5bfe lotr2_game_ai_step_stub 8 Empty stub — reserved step
FUN_004b5c09 0x004b5c09 lotr2_game_ai_army_attack_plan 9 Picks target; spawns attack army
FUN_004bb461 0x004bb461 lotr2_map_ai_pathfind_player_armies 10 Pathfind all active armies for player
FUN_004b4a0a 0x004b4a0a lotr2_game_ai_build_rotation_pass 11 Cycles build type slot
FUN_004b734d 0x004b734d lotr2_game_ai_elimination_taunt_pass 12 Taunt messages strong vs weakest
FUN_004b41d4 0x004b41d4 lotr2_game_ai_prosperity_pass_human_players Build pass for human-controlled players
FUN_004b3116 0x004b3116 lotr2_game_ai_eliminate_defeated_players Loops players 2–5 for elimination
FUN_004b3178 0x004b3178 lotr2_game_ai_eliminate_player Rout figures; clear provinces; defeat message

Pass 34c — Build / economy AI#

Old symbol Address New symbol Evidence
FUN_004b386b 0x004b386b lotr2_game_ai_find_player_capital_tile First tile where province owner == player
FUN_004b4252 0x004b4252 lotr2_game_ai_build_recruit_pass_neutral Build pass for player 0 / unowned tiles
FUN_004b4628 0x004b4628 lotr2_game_ai_apply_troop_build_orders Buys troop types 6/7/8 from player goals
FUN_004b4fa3 0x004b4fa3 lotr2_game_ai_eval_build_slot_feasibility Checks wood/stone vs build costs
FUN_004b9bd1 0x004b9bd1 lotr2_game_ai_build_template_peasant Low-tier build template
FUN_004b9e3d 0x004b9e3d lotr2_game_ai_build_template_basic Minimal food + gold buys
FUN_004b9fbc 0x004b9fbc lotr2_game_ai_build_template_standard Standard prosperity template
FUN_004ba24d 0x004ba24d lotr2_game_ai_build_template_aggressive Aggressive build template
FUN_004ba379 0x004ba379 lotr2_game_ai_build_template_fortified Fortified gold-heavy template
FUN_004ba5fe 0x004ba5fe lotr2_game_ai_adjust_farm_levels Paints farm rects from cattle count
FUN_004ba6ec 0x004ba6ec lotr2_game_ai_optimize_tax_rate Sweeps tax rate 0–100 for best economy
FUN_004ba9a9 0x004ba9a9 lotr2_game_ai_spend_stockpile_resource Negative trade / stockpile spend
FUN_004baa7c 0x004baa7c lotr2_game_ai_buy_resource_with_gold Single resource purchase
FUN_004babab 0x004babab lotr2_game_ai_buy_resource_partial Halving loop until affordable
FUN_004bace2 0x004bace2 lotr2_game_ai_mark_armies_pending_step Sets army pending flag for player/type
FUN_004bae00 0x004bae00 lotr2_game_ai_mark_all_armies_pending Marks all armies of battle type
FUN_004baea8 0x004baea8 lotr2_game_ai_spawn_defender_army Spawns defender from province pop

Pass 34d — Military / siege / army spawn#

Old symbol Address New symbol Evidence
FUN_004b53c0 0x004b53c0 lotr2_game_ai_siege_defender_response Counter-siege army when castle threatened
FUN_004b56c2 0x004b56c2 lotr2_game_ai_province_attack_or_reinforce Compares hostile vs friendly strength
FUN_004b59d1 0x004b59d1 lotr2_game_ai_sum_hostile_army_strength_in_province Sums enemy army strength in tile
FUN_004b5ae2 0x004b5ae2 lotr2_game_ai_sum_friendly_army_strength_in_province Sums own army strength in tile
FUN_004b6a50 0x004b6a50 lotr2_game_ai_pick_primary_secondary_provinces Sets attack target province IDs
FUN_004b5f53 0x004b5f53 lotr2_game_ai_apply_desperation_bonuses Boosts goals when losing
FUN_004b6033 0x004b6033 lotr2_game_ai_commit_army_order Sets army opcode; calls waypoint setters
FUN_004bb183 0x004bb183 lotr2_game_ai_spawn_attack_army Spawns attacker; redistributes troop types
FUN_004bb259 0x004bb259 lotr2_game_ai_army_compose_from_reserve Moves troops from reserve bucket
FUN_004bb315 0x004bb315 lotr2_game_ai_spawn_garrison_from_building Garrison from castle building strength

Pass 34e — Army movement AI (lotr2_map_ai_*)#

Old symbol Address New symbol Evidence
FUN_004b61ff 0x004b61ff lotr2_map_ai_validate_army_merge_target Validates merge destination army
FUN_004b62a3 0x004b62a3 lotr2_map_ai_pick_war_target_player Weakest rival as war target
FUN_004b63c2 0x004b63c2 lotr2_map_ai_pick_nearest_attack_province Chebyshev distance + garrison penalties
FUN_004b65ee 0x004b65ee lotr2_map_ai_pick_nearest_neighbor_province Neighbor province excluding own tiles
FUN_004b6797 0x004b6797 lotr2_map_ai_find_siege_target_province Capturable castle province
FUN_004b68bd 0x004b68bd lotr2_map_ai_pick_best_staging_army Scores idle armies for reinforcement
FUN_004bb5a8 0x004bb5a8 lotr2_map_ai_dispatch_army_by_order_type Switch on army order type 2–6
FUN_004bb6c0 0x004bb6c0 lotr2_map_ai_order_merge_with_friendly Merge order (type 6)
FUN_004bb842 0x004bb842 lotr2_map_ai_order_move_to_target Move/attack order (type 2)
FUN_004bbc2c 0x004bbc2c lotr2_map_ai_order_follow_friendly Follow ally (type 3)
FUN_004bbdda 0x004bbdda lotr2_map_ai_order_siege_capital Siege order (type 4)
FUN_004bbf91 0x004bbf91 lotr2_map_ai_order_assault_garrison Assault order (type 5)
FUN_004bc1eb 0x004bc1eb lotr2_map_ai_set_army_destination Routes to castle vs open waypoint
FUN_004bc2c4 0x004bc2c4 lotr2_map_ai_pick_waypoint_near_castle Scans cells flag 0x80
FUN_004bc456 0x004bc456 lotr2_map_ai_pick_waypoint_near_capital Scans cells flag 0x40

Pass 34f — Diplomacy queue#

Old symbol Address New symbol Evidence
FUN_004b77ee 0x004b77ee lotr2_game_ai_validate_alliance_pairs Fixes broken mutual ally links
FUN_004b7bbc 0x004b7bbc lotr2_game_ai_reset_diplomacy_state Clears queue; resets attitude matrix
FUN_004b7dd5 0x004b7dd5 lotr2_game_ai_pick_first_active_opponent First non-local alive player
FUN_004b84ec 0x004b84ec lotr2_game_ai_clear_diplomacy_queue Zeros 5×6 queue at DAT_0059c230
FUN_004b8589 0x004b8589 lotr2_game_ai_enqueue_diplomacy_action Adds action; may transfer gold
FUN_004b79fb 0x004b79fb lotr2_game_ai_break_alliance Clears mutual ally IDs
FUN_004b771b 0x004b771b lotr2_game_ai_form_alliance Sets mutual ally IDs + flags
FUN_004b769e 0x004b769e lotr2_game_ai_can_attack_player Blocks attack on allies
FUN_004b7e49 0x004b7e49 lotr2_game_ai_apply_diplomacy_attitude_delta Adjusts attitude matrix
FUN_004b8439 0x004b8439 lotr2_game_ai_spread_attitude_to_others Lowers others' opinion of target
FUN_004b7a92 0x004b7a92 lotr2_game_ai_transfer_gold_on_diplomacy Gold transfer on diplomacy action
FUN_004b71e8 0x004b71e8 lotr2_game_ai_pick_ally_candidate Weakest viable non-ally
FUN_004b891a 0x004b891a lotr2_game_ai_diplomacy_tribute_offer Queue type 0
FUN_004b8c3e 0x004b8c3e lotr2_game_ai_diplomacy_trade_request Queue type 1
FUN_004b8ec9 0x004b8ec9 lotr2_game_ai_diplomacy_break_alliance Queue type 2
FUN_004b905e 0x004b905e lotr2_game_ai_diplomacy_propose_alliance Queue type 3
FUN_004b93de 0x004b93de lotr2_game_ai_diplomacy_declare_war Queue type 4
FUN_004b94ba 0x004b94ba lotr2_game_ai_diplomacy_demand_tribute Queue type 5
FUN_004b9845 0x004b9845 lotr2_game_ai_diplomacy_request_marriage Queue type 6

Pass 34g — Battle / conquest entry#

Old symbol Address New symbol Evidence
FUN_004bf4d0 0x004bf4d0 lotr2_game_battle_prep_init_combat Sets battle globals; plays ff_batl.wav
FUN_004bf708 0x004bf708 lotr2_game_battle_on_army_enter_province Army enters tile → battle or conquest
FUN_004bfbc4 0x004bfbc4 lotr2_game_battle_start_from_army_pair Direct battle from two army IDs
FUN_004bfd36 0x004bfd36 lotr2_game_conquest_capture_province Peaceful province capture

See game/MODULE.md turn-sim section, map/MODULE.md army AI cross-links.

Pass 35 — campaign UI / sync cluster (0x43e0000x44ffff)#

Apply source: tools/ghidra/game_renames_pass35.py (imported by apply_anchor_renames.py). 146 FUN_* bodies: turn finalize, battle→campaign transitions, panel hit-tests, MP send wrappers, net remote-apply handlers.

See game/MODULE.md campaign UI section.

Pass 35a — End-turn and player-record chain#

Old symbol Address New symbol Evidence
FUN_004400a0 0x004400a0 lotr2_game_finalize_army_turn 0x1a4 army record; economy/diplomacy tick chain; callee of end-turn / battle exit
FUN_0044035b 0x0044035b lotr2_game_ui_enter_build_screen_mode4 Sets lotr2_game_screen_mode = 4; PL8 reload
FUN_00440389 0x00440389 lotr2_game_ui_reset_campaign_map_view Mode 0 + phase 2 restore
FUN_004403af 0x004403af lotr2_game_ui_hit_test_turn_toolbar Widget table DAT_004f8010 / DAT_004f7fb0 by turn phase
FUN_004404b0 0x004404b0 lotr2_game_ui_on_faction_roster_click lotr2_game_ui_handle_widget_click on DAT_004f8cd0
FUN_00440521 0x00440521 lotr2_game_ui_commit_map_cell_action Map cell + turn phase; SP lotr2_game_apply_map_cell_action_sp, MP opcode 0x22
FUN_00440626 0x00440626 lotr2_game_apply_map_cell_action_sp Diplomacy bucket transfer + economy/diplomacy ticks
FUN_004425e2 0x004425e2 lotr2_game_mp_send_upkeep_increase MP gate; opcode 0x23lotr2_game_increase_player_upkeep
FUN_00442619 0x00442619 lotr2_game_increase_player_upkeep Increments DAT_0055c469; refresh upkeep + move-army dialog
FUN_0044267f 0x0044267f lotr2_game_mp_send_upkeep_decrease MP gate; opcode 0x24
FUN_004426b6 0x004426b6 lotr2_game_decrease_player_upkeep Decrements upkeep counter
FUN_00442c37 0x00442c37 lotr2_game_ui_exit_build_submode Fullscreen dirty; mode 0 or 0x18 by turn phase
FUN_00442c7b 0x00442c7b lotr2_game_apply_build_completion_effects Post-build economy/diplomacy tick chain

Pass 35b — Battle exit / siege outcome#

Old symbol Address New symbol Evidence
FUN_0043f517 0x0043f517 lotr2_game_ui_on_post_battle_return Battle messages 0x94/0x11a; SP siege start or MP opcode 0x2d
FUN_0043f9f7 0x0043f9f7 lotr2_game_start_siege_assault_battle Army pair battle entry from siege flow
FUN_0043f0cf 0x0043f0cf lotr2_game_ui_on_siege_battle_end lotr2_combat_exit_to_campaign; mode 0x11 + s017_01_wav
FUN_0043f2cb 0x0043f2cb lotr2_game_ui_on_siege_assault_start Siege assault battle message enqueue
FUN_0043f781 0x0043f781 lotr2_game_ui_shift_battle_casualty_to_survivors Casualty/survivor counter shift on turn-phase row
FUN_0043f8bc 0x0043f8bc lotr2_game_ui_shift_battle_survivors_to_casualty Inverse casualty shift
FUN_0043ee62 0x0043ee62 lotr2_game_mp_send_finalize_army_turn MP gate; calls lotr2_game_finalize_army_turn; opcode 0x2e
FUN_0043eed7 0x0043eed7 lotr2_game_mp_send_move_army_to_cell MP gate; opcode 0x36lotr2_game_move_army_to_map_cell
FUN_0043ef48 0x0043ef48 lotr2_game_move_army_to_map_cell Pathfind + unlink/link army tile; battle pair check
FUN_0043ec57 0x0043ec57 lotr2_game_ui_enter_army_move_mode Pathfind grid build; sets screen mode for move

Pass 35c — Panel hit-tests and widget clicks#

Old symbol Address New symbol Evidence
FUN_00440f96 0x00440f96 lotr2_game_ui_hit_test_mode5_buildings Mode-5 building grid hit; sets DAT_00593440
FUN_00441238 0x00441238 lotr2_game_ui_hit_test_mode5_panel_row Panel row hit; sets _DAT_0055a360
FUN_00441300 0x00441300 lotr2_game_ui_minimap_tile_at_point Minimap province index from (x,y)
FUN_004413ba 0x004413ba lotr2_game_ui_on_minimap_province_click Minimap click; SP tax transfer or MP opcode 0x25
FUN_0044155c 0x0044155c lotr2_game_ui_apply_minimap_tax_transfer Village tax slider transfer + economy ticks
FUN_00441974 0x00441974 lotr2_game_ui_apply_minimap_province_step Minimap province action step loop
FUN_0043ea1f 0x0043ea1f lotr2_game_ui_hit_test_army_order_bar Army order widget table when army selected
FUN_0043eb24 0x0043eb24 lotr2_game_ui_hit_test_army_detail_panel Army detail panel + portrait hit
FUN_0043e3da 0x0043e3da lotr2_game_ui_hit_test_diplomacy_faction_row Diplomacy faction portrait row hit test
FUN_00441f2b 0x00441f2b lotr2_game_ui_hit_test_build_palette Build palette hit via lotr2_ui_hit_test_point
FUN_004404eb 0x004404eb lotr2_game_ui_on_selected_army_click Stores selected army into DAT_0055a784

Pass 35d — MP opcode send wrappers#

Old symbol Address New symbol Evidence
FUN_0043e21c 0x0043e21c lotr2_game_mp_send_diplomacy_gold_transfer Opcode 0x46; gold transfer on diplomacy
FUN_0043e28f 0x0043e28f lotr2_game_mp_send_diplomacy_alliance Opcode 0x47
FUN_0044301f 0x0044301f lotr2_game_mp_send_enter_battle_mode Opcodes 0x3c / 0x3d battle prep entry
FUN_004430c9 0x004430c9 lotr2_game_mp_send_recruit_unit_inc Opcode 0x37 recruit increment
FUN_00443189 0x00443189 lotr2_game_mp_send_recruit_unit_dec Opcode 0x37 recruit decrement
FUN_00443290 0x00443290 lotr2_game_mp_send_disband_or_merge_army Opcodes 0x38 / 0x39
FUN_004433e9 0x004433e9 lotr2_game_mp_send_toggle_fog_of_war Fog-of-war toggle
FUN_004435f7 0x004435f7 lotr2_game_mp_send_pour_boiling_oil Opcode 0x45; oil spill tiles
FUN_00443859 0x00443859 lotr2_game_ui_on_battle_scroll_drag Battle scroll; MP opcode 0x41
FUN_00443b7c 0x00443b7c lotr2_game_ui_on_battle_figure_click Figure pick; opcodes 0x42 / 0x44
FUN_004427c8 0x004427c8 lotr2_game_mp_send_end_ai_turn Opcode 0x1e; AI turn counter 999
FUN_00447dc0 0x00447dc0 lotr2_net_host_poll_sync_ready_loop Host sync poll; sends opcode 0x10

Full opcode→handler table for 0x44f000 remote-apply stubs: see _FUN dict in game_renames_pass35.py (lotr2_net_apply_remote_*).

Pass 35e — Stubs and leaf helpers#

Old symbol Address New symbol Evidence
FUN_0043ed42 0x0043ed42 lotr2_game_ui_noop_ed42 Empty return; Ghidra padding
FUN_0044295b 0x0044295b lotr2_game_ui_noop_295b Empty return
FUN_00444d39 0x00444d39 lotr2_game_ui_noop_4d39 Empty return
FUN_004442b1004444c2 0x004442b1… lotr2_game_ui_noop_* Empty/thunk padding cluster
FUN_0044f17b0044f598 0x0044f17b… lotr2_net_apply_remote_* Net unpack dispatch targets (thin apply wrappers)

Pass 36 — castle / build / recruit (0x004c00000x004cffff)#

Full 109-symbol list: tools/ghidra/game_renames_pass36.py.

Pass 36a — Build queue and castle placement#

Old symbol Address New symbol Evidence
FUN_004c0322 0x004c0322 lotr2_game_build_commit_action Routes build action; sets DAT_0055ad90 / DAT_00543634 for MP
FUN_004c0380 0x004c0380 lotr2_game_build_restore_after_mp34 Restores screen mode; MP opcode 0x34 or replays build
FUN_004c03db 0x004c03db lotr2_game_build_place_on_province Province placement; lotr2_combat_unlink_province_army_tile; merge via FUN_004c2ad7
FUN_004c06da 0x004c06da lotr2_game_build_try_open_castle_view Gates on province owner; calls start-castle-action
FUN_004c07e7 0x004c07e7 lotr2_game_build_restore_after_mp35 Restores screen mode; MP opcode 0x35
FUN_004c0842 0x004c0842 lotr2_game_build_start_castle_action Sets lotr2_game_screen_mode = 0x1d; links army/province
FUN_004c08ed 0x004c08ed lotr2_game_build_reset_slot_queue Zeros 3×6-byte build sub-slots; castle type table DAT_004f3bd8
FUN_004c0afb 0x004c0afb lotr2_game_build_calc_queue_percent lotr2_game_ratio_percent over build queue slots
FUN_004c0cd9 0x004c0cd9 lotr2_game_build_reconcile_all_slots Reconcile province/army links; sets lotr2_game_build_slot_index = 1
FUN_004c0e3c 0x004c0e3c lotr2_game_build_validate_slot_province_link Validates DAT_00564569 vs province army owner
FUN_004c0eca 0x004c0eca lotr2_game_build_find_active_slot Scans slots from lotr2_game_build_slot_index; calls progress tick
FUN_004c0f17 0x004c0f17 lotr2_game_build_tick_slot_progress Advances 3-slot build progress per turn labor

Pass 36b — Siege assault and map battle prep#

Old symbol Address New symbol Evidence
FUN_004c14bb 0x004c14bb lotr2_game_battle_start_siege_assault Siege assault entry; modes 0x12/0x13; s080_*.wav
FUN_004c1766 0x004c1766 lotr2_game_battle_init_pathfind_from_army lotr2_combat_reset_pathfind_search from army cell
FUN_004c17d5 0x004c17d5 lotr2_game_battle_update_pathfind_cursor Map click pathfind; sets attack/move/merge targets
FUN_004c1b71 0x004c1b71 lotr2_game_battle_mark_allied_capital_cells Marks allied capital tiles on pathfind grid
FUN_004c1c0a 0x004c1c0a lotr2_game_battle_on_map_click_dispatch Modal dispatch from pathfind target flags
FUN_004c1d2a 0x004c1d2a lotr2_game_battle_modal_attack_confirm Attack confirm; MP opcode 0x29
FUN_004c1fc7 0x004c1fc7 lotr2_game_battle_modal_move_confirm Move-to-empty confirm
FUN_004c2115 0x004c2115 lotr2_game_battle_modal_merge_confirm Merge armies confirm; MP opcode 0x2c
FUN_004c21f3 0x004c21f3 lotr2_game_battle_modal_attack_neutral Attack neutral province confirm
FUN_004c22b6 0x004c22b6 lotr2_game_army_set_march_waypoints Sets march waypoints; lotr2_combat_copy_province_army_waypoints

Pass 36c — Recruit spawn and army merge#

Old symbol Address New symbol Evidence
FUN_004c23f1 0x004c23f1 lotr2_game_recruit_spawn_army Full recruit: spawn, economy/diplomacy tick, gold debit
FUN_004c2807 0x004c2807 lotr2_game_recruit_debit_faction_units Debits faction unit tallies; lotr2_game_sum_faction_build_totals
FUN_004c286e 0x004c286e lotr2_game_recruit_debit_province_gold_pool Debits province gold pools on recruit
FUN_004c28c8 0x004c28c8 lotr2_game_recruit_pick_unit_type_row Picks lowest-priority unit type row (DAT_0055adcd)
FUN_004c298f 0x004c298f lotr2_game_army_release_and_clear_links lotr2_combat_release_province_army; clears province links
FUN_004c2ad7 0x004c2ad7 lotr2_game_army_merge_into Merges two army slots; sums unit counts and build queue
FUN_004c3020 0x004c3020 lotr2_game_battle_copy_build_icons_to_slot Copies build icons for battle prep display
FUN_004c31f5 0x004c31f5 lotr2_game_battle_clear_build_icon_slot Clears battle prep icon fields
FUN_004c3260 0x004c3260 lotr2_game_faction_reset_build_templates Resets faction build template rows (0x80 stride)
FUN_004c33d6 0x004c33d6 lotr2_game_faction_reset_build_templates_b Variant build-template reset
FUN_004c352e 0x004c352e lotr2_game_trade_load_troop_pl8_preview Loads trp_xb_*.pl8 trade preview sprites

Pass 36d — Siege outcome and raid/pillage#

Old symbol Address New symbol Evidence
FUN_004c365d 0x004c365d lotr2_game_battle_apply_casualty_split Applies siege casualty split between attacker/defender
FUN_004c3c05 0x004c3c05 lotr2_game_army_calc_combat_strength Weighted sum of unit counts × DAT_004f9f60
FUN_004c3cde 0x004c3cde lotr2_game_battle_resolve_siege_outcome Post-siege capture, ff_lose.wav, end-turn chain
FUN_004c42f3 0x004c42f3 lotr2_game_battle_on_defender_routed Routed defender gold transfer + army release
FUN_004c43cf 0x004c43cf lotr2_game_raid_enter_enemy_province Raid entry; pillage message enqueue
FUN_004c45a8 0x004c45a8 lotr2_game_raid_apply_pillage_gold Pillages province gold; may spawn neutral army
FUN_004c4810 0x004c4810 lotr2_game_raid_enqueue_strength_message Raid strength ratio battle messages (0x820x86)
FUN_004c4a1e 0x004c4a1e lotr2_game_raid_spawn_neutral_army Spawns neutral defender on pillage
FUN_004c4c5f 0x004c4c5f lotr2_game_raid_clear_province_owner Clears province owner; economy tick
FUN_004c4d26 0x004c4d26 lotr2_game_ai_march_idle_armies AI pathfind march for idle garrison armies
FUN_004c4e47 0x004c4e47 lotr2_game_ai_assign_march_target_province Rotates AI march target province index
FUN_004c4f8b 0x004c4f8b lotr2_game_army_remove_recruit_bonus Removes recruit bonus unit from army strength
FUN_004c5080 0x004c5080 lotr2_game_recruit_apply_flag_bonus Applies recruit flag bonus from DAT_00582ff0 table

Pass 36e — Upkeep, flags, and faction totals#

Old symbol Address New symbol Evidence
FUN_004c5191 0x004c5191 lotr2_game_recruit_init_flag_table Loads recruit flag table; lotr2_combat_clear_all_flag_slots
FUN_004c52b9 0x004c52b9 lotr2_game_recruit_advance_flag_rotation Rotates recruit flag assignments per player
FUN_004c53e2 0x004c53e2 lotr2_game_recruit_find_flag_for_player Finds free flag slot for player id
FUN_004c5462 0x004c5462 lotr2_game_upkeep_check_faction_budgets Faction upkeep budget warnings (messages 0xa00x111)
FUN_004c56eb 0x004c56eb lotr2_game_upkeep_tick_army_slots Per-army upkeep starvation tick
FUN_004c5975 0x004c5975 lotr2_game_upkeep_apply_penalty_to_faction Applies upkeep penalty across faction armies
FUN_004c59f9 0x004c59f9 lotr2_game_upkeep_reduce_army_strength 10% unit count reduction on upkeep fail
FUN_004c5abd 0x004c5abd lotr2_game_upkeep_disband_recruit_bonuses Disbands recruit bonus units under upkeep pressure
FUN_004c5ba3 0x004c5ba3 lotr2_game_upkeep_disband_faction_armies Disbands all faction armies on bankruptcy
FUN_004c5c27 0x004c5c27 lotr2_game_upkeep_release_routed_armies Releases routed armies after upkeep pass
FUN_004c5cb3 0x004c5cb3 lotr2_game_upkeep_refresh_faction_totals Refreshes per-faction army strength totals
FUN_004c5d22 0x004c5d22 lotr2_game_sum_faction_army_strength Sums upkeep shares for all faction armies
FUN_004c5db8 0x004c5db8 lotr2_game_calc_army_upkeep_share Difficulty-scaled army upkeep fraction
FUN_004c5f4d 0x004c5f4d lotr2_game_refresh_province_gold_totals Aggregates army strength into province gold pools
FUN_004c6159 0x004c6159 lotr2_game_battle_halve_loser_army_strength Halves losing army unit counts post-battle

Pass 36f — Castles.dat, stubs, audio, castle-view blit#

Old symbol Address New symbol Evidence
FUN_004c8ad8 0x004c8ad8 lotr2_game_history_clear_ring_buffer Clears 400×16 province gold history ring
FUN_004c8b68 0x004c8b68 lotr2_game_history_record_province_gold Records province gold snapshot into ring
FUN_004c8c34 0x004c8c34 lotr2_game_castles_dat_create_blank Creates blank castles.dat (16×0x3200)
FUN_004c8cf3 0x004c8cf3 lotr2_game_castles_dat_write_player_layout Writes one player castle layout slice
FUN_004c9e67 0x004c9e67 lotr2_asset_path_len_to_dot Returns path length to first . (extension probe helper)
FUN_004cece1 0x004cece1 lotr2_game_play_battle_sfx_by_id Battle SFX bank (S100_*, S200_*, kt170_*)
FUN_004cede0004cf2b2 0x004cede0… lotr2_game_play_*_sfx_* UI/battle WAV cue helpers (S010S246 tables)
FUN_004ceedc 0x004ceedc lotr2_game_play_build_or_siege_sfx Build/siege context SFX (S031_*, S071_*)
FUN_004cf4c0 0x004cf4c0 lotr2_gfx_rle_pack_buffer RLE pack for castle-view tile data
FUN_004cf5a9 0x004cf5a9 lotr2_gfx_rle_unpack_buffer RLE unpack
FUN_004cf774004cfbe2 0x004cf774… lotr2_gfx_*_backbuf_* Castle-view software backbuf blit/fill helpers
FUN_004c9000004c9062 0x004c9000… lotr2_game_stub_* / lotr2_game_noop_* Empty vtable/stub slots
FUN_004cec70004cec86 0x004cec70… lotr2_game_noop_cec* Empty returns adjacent to intro hook

Pass 37 — castle interior / gateway UI (0x41f0000x425fff)#

Pass 37a — Armoury and province overview#

Old symbol Address New symbol Evidence
FUN_0041ff10 0x0041ff10 lotr2_game_ui_refresh_armoury_screen Reloads armoury.256/armoury.pl8; called on mode 0x0d0x0a transition
FUN_00420005 0x00420005 lotr2_game_ui_draw_armoury_stat_rows Blits 8 build-slot sprites + number fields; player stride 0x160
FUN_00420243 0x00420243 lotr2_game_ui_blit_armoury_build_slots Blits slots 1–6 from DAT_004ed920 when build counts > 0
FUN_004202e3 0x004202e3 lotr2_game_ui_draw_armoury_weapon_panel Loads arm_cros.pl8arm_mail.pl8 by DAT_0055a37c weapon type
FUN_00420c4c 0x00420c4c lotr2_game_ui_draw_armoury_weapon_stats Weapon name + stock delta in armoury detail subpanel
FUN_00421062 0x00421062 lotr2_game_ui_blit_armoury_torch_icons Blits torch sprite sheet at fixed armoury chrome coords
FUN_00420470 0x00420470 lotr2_game_ui_draw_province_overview_panel Mode 0x17; province stride 0x300; gold/population summary panel

Pass 37b — Castle intro, post-siege, siege prep#

Old symbol Address New symbol Evidence
FUN_00420de4 0x00420de4 lotr2_game_ui_blit_castle_backdrop_strip Copies panels2.pl8 strip slice into backbuf by scroll offset
FUN_00420efa 0x00420efa lotr2_game_ui_tick_castle_intro_carriage Animates carriage sprite along intro scroll (DAT_00543550)
FUN_00422d83 0x00422d83 lotr2_game_ui_reset_castle_intro_anim Zeros intro scroll globals _DAT_00573c08 / _DAT_00583130
FUN_004210d0 0x004210d0 lotr2_game_ui_enter_post_siege_screen Mode 0x11; loads icon_tmp.pl8; post-siege battle result chrome
FUN_00421173 0x00421173 lotr2_game_ui_draw_post_siege_unit_rows Draws 7 unit-type buy/sell rows on post-siege screen
FUN_004215a8 0x004215a8 lotr2_game_ui_enter_siege_battle_prep_screen Mode 0x1b; loads cas_back.256, caspics.pl8, cas_bits.pl8
FUN_004216c9 0x004216c9 lotr2_game_ui_draw_siege_battle_prep_hud Siege prep defender/attacker counts + eng strings (table 0x47)

Pass 37c — Status bar, text helpers, diplomacy minimap#

Old symbol Address New symbol Evidence
FUN_00421a97 0x00421a97 lotr2_game_ui_draw_status_bar_overlay Bottom status strip; debug mem panel; player icon row
FUN_00421f23 0x00421f23 lotr2_game_ui_draw_localized_credits_banner Non-English locale credits scroll via table 0x12d
FUN_0042236a 0x0042236a lotr2_game_ui_draw_debug_memory_panel Profiler text: DAT_005053d0, DAT_00504270, DAT_005ec390
FUN_004223f6 0x004223f6 lotr2_game_ui_draw_pending_orders_badge Pending-order count badge when DAT_0055ac0c > 0
FUN_004224a4 0x004224a4 lotr2_game_ui_draw_human_turn_label Human player name label on campaign map toolbar
FUN_004225b4 0x004225b4 lotr2_game_ui_draw_mp_sync_wait_blink MP sync wait rectangle blink when lotr2_net_session_active
FUN_00422670 0x00422670 lotr2_game_ui_draw_signed_value_captioned Signed number + eng prefix by style param (gold/pop variants)
FUN_004228d7 0x004228d7 lotr2_game_ui_draw_number_with_table_caption Number field + table-8 eng caption; widely used UI helper
FUN_004229ae 0x004229ae lotr2_game_ui_draw_table8_caption_only Draw eng string from table 8 without leading number
FUN_00422a05 0x00422a05 lotr2_game_ui_draw_signed_delta_with_glyph Signed delta row with +/- glyph sprite
FUN_00422acd 0x00422acd lotr2_game_ui_draw_diplomacy_minimap_panel Mode 0x18; minimap + faction summary panel
FUN_00422c12 0x00422c12 lotr2_game_ui_draw_diplomacy_offer_stats_panel Diplomacy offer gold/army stat subpanel (table 0x21)

Pass 37d — Province event popups and gateway#

Old symbol Address New symbol Evidence
FUN_00422da2 0x00422da2 lotr2_game_ui_present_province_event_popup Yields, marks dirty, dispatches owned vs generic popup, presents frame
FUN_00422df1 0x00422df1 lotr2_game_ui_draw_siege_assault_icon_row Mode 0x10; siege assault unit icon row for local player army
FUN_00422f0d 0x00422f0d lotr2_game_ui_draw_province_event_popup_owned Owned-province event popup; army record stride 0x1a4
FUN_00423c6e 0x00423c6e lotr2_game_ui_setup_province_event_chrome Sets panel layout from lotr2_game_province_event_flags event-flag bitmask
FUN_00423f78 0x00423f78 lotr2_game_ui_draw_province_event_body Event body text/icons; branches on lotr2_game_province_event_flags flags
FUN_00424706 0x00424706 lotr2_game_ui_draw_province_event_owner_panel Extra owner-only panel when event flag 0x20 set
FUN_004248aa 0x004248aa lotr2_game_ui_draw_province_economy_event_panel Economy event popup (local_20 == 0x13 path from body draw)
FUN_0042500d 0x0042500d lotr2_game_ui_draw_province_build_event_panel Build/production event popup (local_20 == 0x15 path)
FUN_004257ab 0x004257ab lotr2_game_ui_draw_province_harvest_event_panel Harvest/yield event popup; calls capital stats row
FUN_00425c57 0x00425c57 lotr2_game_ui_draw_province_capital_stats_row Province capital build/gold stats row (table 0x47)
FUN_00425f59 0x00425f59 lotr2_game_ui_enter_gateway_screen Loads gateway.256/gateway.pl8/panels2.pl8; new-game text rows

Pass 38 — wizard / turn-action table (0x43b0000x43dfff)#

See game/MODULE.md. Apply source: tools/ghidra/game_renames_pass38.py.

Pass 38a — Wizard / lobby helpers#

Old symbol Address New symbol Evidence
FUN_0043b844 0x0043b844 lotr2_game_wizard_noop_b844 Empty stub; neighbor of lotr2_game_wizard_set_config_value
FUN_0043bb91 0x0043bb91 lotr2_game_wizard_open_options_modal lotr2_game_ui_enter_modal_mode(1,0xa0,0xa0,&LAB_004034cc)
FUN_0043bbb5 0x0043bbb5 lotr2_game_wizard_cancel_and_resume Restores lotr2_game_screen_mode; SP tick or MP net opcode 0x19
FUN_0043bee1 0x0043bee1 lotr2_game_wizard_set_loading_progress_100 Sets DAT_005bc614 = 100 (loading bar)
FUN_0043bfba 0x0043bfba lotr2_game_wizard_cancel_overlay_step When DAT_005bc768; sets DAT_005ae7e8 = 3 or restores screen mode

Pass 38b — Turn-action table no-op slots#

Old symbol Address New symbol Evidence
FUN_0043c75a 0x0043c75a lotr2_game_action_noop_c75a Empty return; between named pass-26 actions
FUN_0043c765 0x0043c765 lotr2_game_action_noop_c765 Empty table slot
FUN_0043c770 0x0043c770 lotr2_game_action_noop_c770 Empty table slot
FUN_0043c77b 0x0043c77b lotr2_game_action_noop_c77b Empty table slot
FUN_0043c786 0x0043c786 lotr2_game_action_noop_c786 Empty table slot
FUN_0043c791 0x0043c791 lotr2_game_action_noop_c791 Empty table slot
FUN_0043c79c 0x0043c79c lotr2_game_action_noop_c79c Empty table slot
FUN_0043c7a7 0x0043c7a7 lotr2_game_action_noop_c7a7 Empty table slot
FUN_0043c7b2 0x0043c7b2 lotr2_game_action_noop_c7b2 Empty table slot
FUN_0043c7bd 0x0043c7bd lotr2_game_action_noop_c7bd Empty table slot
FUN_0043c7c8 0x0043c7c8 lotr2_game_action_noop_c7c8 Empty table slot before lotr2_game_action_toggle_flag_b874
FUN_0043c87b 0x0043c87b lotr2_game_action_noop_c87b Empty slot after mode-0x31 action
FUN_0043c886 0x0043c886 lotr2_game_action_noop_c886 Empty slot before mode-0x25 action
FUN_0043c911 0x0043c911 lotr2_game_action_noop_c911 Empty slot in toolbar cluster
FUN_0043cab7 0x0043cab7 lotr2_game_action_noop_cab7 Empty slot before castle-view toggle
FUN_0043ccd4 0x0043ccd4 lotr2_game_action_noop_ccd4 Empty slot before diplomacy entry
FUN_0043ccdf 0x0043ccdf lotr2_game_action_noop_ccdf Empty stub; callee of overlay arm action
FUN_0043ccea 0x0043ccea lotr2_game_action_noop_ccea Empty slot before diplomacy init
FUN_0043cdac 0x0043cdac lotr2_game_action_noop_cdac Empty slot before replay entry
FUN_0043d2cc 0x0043d2cc lotr2_game_action_noop_d2cc Empty slot after battle replay speed setter

Pass 38c — Toolbar / overlay / scroll helpers#

Old symbol Address New symbol Evidence
FUN_0043c84f 0x0043c84f lotr2_game_action_request_overlay_redraw Calls lotr2_game_action_redraw_overlay
FUN_0043c8fc 0x0043c8fc lotr2_game_action_set_toolbar_timer_10 Sets DAT_005bc72c = 10
FUN_0043c91c 0x0043c91c lotr2_game_action_set_toolbar_timer_10_alt Duplicate timer set on DAT_005bc72c
FUN_0043c931 0x0043c931 lotr2_game_action_arm_toolbar_overlay Sets _DAT_005bc730 = 1 and DAT_005bc72c = 10
FUN_0043c975 0x0043c975 lotr2_game_action_set_lobby_active_flag Sets DAT_005bc768 = 1 (see lotr2_game_reset_lobby_flags)
FUN_0043c987 0x0043c987 lotr2_game_action_clear_lobby_active_flag Clears DAT_005bc768
FUN_0043c9ba 0x0043c9ba lotr2_game_action_set_lobby_step_10 Sets DAT_005bc728 = 10
FUN_0043c9cf 0x0043c9cf lotr2_game_action_zoom_scroll_in Increments *DAT_005ec498 by DAT_005ae7f0
FUN_0043c9fa 0x0043c9fa lotr2_game_action_zoom_scroll_out Decrements scroll pointer when above min
FUN_0043ca84 0x0043ca84 lotr2_game_action_finish_setup_or_play_intro Phase 0 → mode 0; else plays intro SMK via FUN_00436725
FUN_0043cac2 0x0043cac2 lotr2_game_action_ui_message_yield Calls lotr2_ui_noop_8d6 (message pump hook)

Pass 38d — Diplomacy / replay entry#

Old symbol Address New symbol Evidence
FUN_0043ccba 0x0043ccba lotr2_game_action_arm_diplomacy_overlay Calls noop stub then sets _DAT_005bc730 = 1
FUN_0043cd7f 0x0043cd7f lotr2_game_action_store_diplomacy_sfx_index Stores turn phase in DAT_00583108; lotr2_game_play_ui_sfx_s035
FUN_0043cdb7 0x0043cdb7 lotr2_game_action_enter_replay_mode SP calls stat adjuster FUN_00432f3e; MP sends opcode 0x28; mode 8
FUN_0043ce23 0x0043ce23 lotr2_game_action_enter_replay_screen_only Sets screen mode 8 without replay stat apply

Pass 38e — Replay speed controls#

Old symbol Address New symbol Evidence
FUN_0043d072 0x0043d072 lotr2_game_action_set_replay_speed_campaign Sets DAT_00563d24 from DAT_0055f6c4; plays s068_02_wav; calls lotr2_game_replay_update_speed_tier
FUN_0043d10c 0x0043d10c lotr2_game_action_set_replay_speed_battle Sets speed from DAT_0059c37c; plays s068_01_wav; updates speed tier

Pass 38f — Build-queue slot ops (armoury mode 0xd)#

Old symbol Address New symbol Evidence
FUN_0043d46b 0x0043d46b lotr2_game_action_build_queue_increment_slot Increments slot at DAT_0055a380 + slot*0x10 + player*0x80
FUN_0043d4ed 0x0043d4ed lotr2_game_action_build_queue_decrement_slot Decrements selected build-queue slot count
FUN_0043d53d 0x0043d53d lotr2_game_action_build_queue_clear_slot Drains slot count back to pool
FUN_0043d592 0x0043d592 lotr2_game_action_build_queue_fill_slot Fills slot to max from pool
FUN_0043d7ba 0x0043d7ba lotr2_game_action_toggle_province_economy_flag Sets DAT_0059e644 from turn phase == 1
FUN_0043d7f0 0x0043d7f0 lotr2_game_action_enter_trade_screen Mode 10; lotr2_game_faction_reset_build_templates

Pass 38g — Diplomacy text-input flows (screen mode 0x1a)#

Old symbol Address New symbol Evidence
FUN_0043db63 0x0043db63 lotr2_game_action_enter_diplomacy_text_mode_0 Mode 0x1a; DAT_00563e54 = 0; yield + map redraw
FUN_0043dbad 0x0043dbad lotr2_game_action_enter_diplomacy_text_mode_1 Sub-type 1; loads string buffer DAT_0059b8d8
FUN_0043dbfc 0x0043dbfc lotr2_game_action_enter_diplomacy_text_mode_2 Sub-type 2; loads DAT_0059b9a0
FUN_0043dc4b 0x0043dc4b lotr2_game_action_enter_diplomacy_text_mode_3_or_4 Sub-type 3 or 4 by faction match; loads DAT_0059ba68/bb30
FUN_0043dcec 0x0043dcec lotr2_game_action_enter_diplomacy_text_mode_5 Sub-type 5; clears DAT_005930e4
FUN_0043dd40 0x0043dd40 lotr2_game_action_enter_diplomacy_text_mode_6 Sub-type 6; same yield pattern as mode 5
FUN_0043dd94 0x0043dd94 lotr2_game_action_adjust_diplomacy_gold_offer Adjusts DAT_00582dac ±10 by turn phase; clamps to faction gold
FUN_0043de2a 0x0043de2a lotr2_game_action_apply_diplomacy_text_submit Applies text by sub-type; SP lotr2_game_ai_enqueue_diplomacy_action; MP opcodes 0x48/0x49

Pass 39 — wizard step renderers (0x4260000x427fff)#

See game/MODULE.md. Apply source: tools/ghidra/game_renames_pass39.py.

Continues pass 37 gateway entry (lotr2_game_ui_enter_gateway_screen @ 0x425f59). Draw chain for screen mode 0x1f; sub-steps via lotr2_game_wizard_step (1–8).

Pass 39a — Asset load + step dispatcher#

Old symbol Address New symbol Evidence
FUN_0042634c 0x0042634c lotr2_game_wizard_load_step_assets Loads gateway/custom/panels2 by wizard step; applies palette
FUN_00426498 0x00426498 lotr2_game_wizard_redraw_current_step Mode 0x1f; dispatches wizard steps 1–8
FUN_00426596 0x00426596 lotr2_game_wizard_draw_loading_message Loading overlay panel + lotr2_gfx_present_frame

Pass 39b — Steps 1–4 panels and name input#

Old symbol Address New symbol Evidence
FUN_00426648 0x00426648 lotr2_game_wizard_draw_step1_panel Step 1 bordered panel; eng table 0xb rows 0–1
FUN_004266d7 0x004266d7 lotr2_game_wizard_draw_step1_option_rows 3 selectable rows; highlight via selection index
FUN_00426849 0x00426849 lotr2_game_wizard_draw_step2_panel Step 2 panel; eng row 5
FUN_004268a5 0x004268a5 lotr2_game_wizard_draw_step2_option_rows 4 selectable option rows (step 2)
FUN_00426a8c 0x00426a8c lotr2_game_wizard_draw_step3_load_panel Calls lotr2_game_ui_draw_load_wizard_panel(5)
FUN_00426aa1 0x00426aa1 lotr2_game_wizard_draw_step4_name_panel Name text input; MP host/client panel height branch
FUN_00426b7a 0x00426b7a lotr2_game_wizard_draw_step4_mp_options MP-only bottom option rows
FUN_00426c9c 0x00426c9c lotr2_game_wizard_blit_player_slot_icons Blits 5 player slot sprites from panels2 sheet
FUN_00426dd3 0x00426dd3 lotr2_game_wizard_draw_name_text_input Renders typed name + blinking cursor

Pass 39c — Steps 5–8 setup, map, and player rows#

Old symbol Address New symbol Evidence
FUN_00426e9b 0x00426e9b lotr2_game_wizard_draw_step5_sp_setup SP config step; map size + player slot draw
FUN_00426f4e 0x00426f4e lotr2_game_wizard_draw_step6_mp_setup MP host config; extra eng rows + ruler name load
FUN_00427073 0x00427073 lotr2_game_wizard_draw_config_value_rows 12 wrapped config labels; dims non-selected row
FUN_00427191 0x00427191 lotr2_game_wizard_draw_map_size_selector Minimap + map-size bar + size labels
FUN_004273dc 0x004273dc lotr2_game_wizard_draw_player_slot_rows lotr2_game_ai_assign_nation_culture_slots; nation icons + names
FUN_004275e7 0x004275e7 lotr2_game_wizard_draw_step7_player_count Player-count panel; reuses step 5/6 setup
FUN_00427747 0x00427747 lotr2_game_wizard_draw_mp_player_list MP session player name scroll list
FUN_00427853 0x00427853 lotr2_game_wizard_draw_step6_name_field MP ruler name text input overlay
FUN_00427968 0x00427968 lotr2_game_wizard_draw_step8_panel Final wizard step panel; wrapped eng rows 0x11–0x12
FUN_00427a17 0x00427a17 lotr2_game_ui_draw_siege_assault_prep_panel Screen mode 0x1d; loads sgeplans.pl8; army unit sliders

Pass 40 — map runtime/draw + Smacker video (0x432000–0x437fff)#

Ghidra mislabels Smacker SDK imports as DirectPlayCreate4, DirectPlayEnumerate3, etc. Evidence: .smk path buffer DAT_00530e20, s_intro_smk_004efdb8, blit to lotr2_gfx_backbuf_pixels, caller lotr2_video_play_smk. Do not rename these to lotr2_net_*.

Pass 40a — Map runtime: armies, probes, economy hooks#

Old symbol Address New symbol Evidence
FUN_00432940 0x00432940 lotr2_map_spawn_starting_armies_from_list Iterates DAT_00573bc0; cell probes; lotr2_map_spawn_province_army_at_cell
FUN_00432a77 0x00432a77 lotr2_map_cell_has_nearest_flag_ring Rings 1–3 via lotr2_map_find_nearest_cell_flag
FUN_00432ae8 0x00432ae8 lotr2_map_cell_has_passable_rect_ring Rings 1–3 via lotr2_map_rect_has_passable_cell
FUN_00432b59 0x00432b59 lotr2_map_tick_province_army_pathfind Army record stride 0x1a4; lotr2_combat_run_pathfind_search
FUN_00432eec 0x00432eec lotr2_map_init_province_cost_table Copies DAT_004f39f0 defaults into DAT_00563d50
FUN_00432f3e 0x00432f3e lotr2_game_apply_resource_delta Per-player 0x300 counters; economy/diplomacy tick chain
FUN_00433474 0x00433474 lotr2_map_apply_population_growth Gold spend → DAT_0055c3bc / DAT_0055c5c9 population tiers
FUN_004335e1 0x004335e1 lotr2_game_calc_build_turn_cost Build-turn cost from DAT_0059e620 resource type + army record
FUN_004339e4 0x004339e4 lotr2_map_build_layer_province_chains Walks DAT_0055b750 layer lists into DAT_00573bc0
FUN_00433a8f 0x00433a8f lotr2_map_layer_has_province_id Membership test in 6-byte DAT_00573bc0 table
FUN_00433ae0 0x00433ae0 lotr2_map_spawn_reinforcement_army Spawn type-4 army; deducts gold/food from province
FUN_00433c49 0x00433c49 lotr2_map_tick_conquest_army_pathfind Type-4 armies; same pathfind pattern as 00432b59
FUN_00433ee6 0x00433ee6 lotr2_map_on_province_army_conquered Transfers loot; economy tick; lotr2_combat_release_province_army

Pass 40b — Map draw: grid, viewport, tile stamps#

Old symbol Address New symbol Evidence
FUN_004345e0 0x004345e0 lotr2_map_find_cell_by_tile_index Scans 0x81×0x41 grid at DAT_005934e0
FUN_004348fb 0x004348fb lotr2_map_clamp_viewport_origin Clamps DAT_0055ac6c/DAT_0055ac70 to map bounds
FUN_00434982 0x00434982 lotr2_map_hit_test_cell_from_cursor Mouse coords → grid cell; sets DAT_00573c20 tile index
FUN_00434cf0 0x00434cf0 lotr2_map_rotate_grid_view_cw lotr2_map_init_province_grid; viewport remap
FUN_00434df9 0x00434df9 lotr2_map_rotate_grid_view_ccw Counter-clockwise variant of 00434cf0
FUN_00434f3d 0x00434f3d lotr2_map_sync_cursor_to_cell_origin Syncs _DAT_005257b4/DAT_005257c4 from hit-test row/col
FUN_0043500d 0x0043500d lotr2_map_stamp_tile_pattern_small 9-call composite around lotr2_map_draw_cell_tile
FUN_004350ec 0x004350ec lotr2_map_stamp_tile_pattern_large 11-call composite around lotr2_map_draw_cell_tile
FUN_00435263 0x00435263 lotr2_map_draw_cell_tile 0x81×0x41 bounds; tile table; gfx glyph blit dispatch
FUN_004355d1 0x004355d1 lotr2_map_blit_map_sprite_scaled Reads DAT_0059bfd0 sprite header; view-mode gfx blit
FUN_004356b1 0x004356b1 lotr2_map_blit_map_sprite_unscaled Unscaled map sprite blit variant
FUN_0043578b 0x0043578b lotr2_map_blit_map_sprite_alt Third view-mode blit path for map sprites

Pass 40c — Smacker video decode + DirectDraw surface helpers#

Old symbol Address New symbol Evidence
FUN_00435d6e 0x00435d6e lotr2_video_play_smk_and_close Opens via lotr2_video_open_smk_file; closes Smacker on success
FUN_00435e18 0x00435e18 lotr2_video_open_smk_file Asset path resolve; DirectPlayCreate4 (Smacker open); first frame decode
FUN_00435fc7 0x00435fc7 lotr2_video_decode_and_blit_frame Per-frame loop; DirectPlayEnumerate3 → backbuf; intro credits overlay
FUN_00436330 0x00436330 lotr2_video_close_and_restart_cutscene Smacker close; lotr2_video_start_cutscene
FUN_004363e2 0x004363e2 lotr2_video_close_smk Close without cutscene restart
FUN_0043663c 0x0043663c lotr2_video_copy_smacker_palette Copies 256×RGB from Smacker context offset 0x6c
FUN_004366c4 0x004366c4 lotr2_video_init_smacker_audio_once One-shot Ordinal_37(lotr2_audio_lpds)
FUN_00436706 0x00436706 lotr2_video_apply_smacker_palette Palette copy + lotr2_gfx_update_dd_palette
FUN_00436725 0x00436725 lotr2_video_play_intro_variant Dispatches Intro.smk variant by DAT_00582d6c
FUN_0043675e 0x0043675e lotr2_video_smacker_wndproc_paint BeginPaint/PatBlt; Smacker frame advance on windowed mode
FUN_004368b1 0x004368b1 lotr2_video_blit_frame_to_primary Full 640×480 DD blit from dirty-rect globals
FUN_0043714b 0x0043714b lotr2_gfx_release_surfaces Release primary/backbuf/clipper; optional IDirectDraw release
FUN_00437221 0x00437221 lotr2_gfx_lock_primary_surfaces Lock primary (and backbuf in hicolor) for Smacker init
FUN_00437336 0x00437336 lotr2_gfx_create_surfaces_and_backbuf Create primary + offscreen backbuf; attach clipper
FUN_00437c5f 0x00437c5f lotr2_gfx_ddraw_hresult_to_msg_index Maps DDERR_* HRESULTs to loading-msg string table index

Deferred (empty stubs, zero or noop callers): FUN_00432ee1, FUN_00435d10, FUN_0043abfd, FUN_0043ac0f, FUN_0043ad6f.

Pass 41 — isometric backbuffer stamp/fill (0x460000–0x46ffff)#

Largest remaining game-code FUN_* cluster before this pass (~44 symbols). Bodies read/write lotr2_gfx_backbuf_pixels and lotr2_gfx_backbuf_stride; shared by map draw, combat message panel, and UI paint. Apply: tools/ghidra/gfx_stamp_renames_pass41.py.

Pass 41a — Map cell isometric fill (lotr2_map_draw_cell_tile)#

Dispatched on DAT_0055a898 (view rotation 0–2) and DAT_00582fe8 (edge clip 0/1/2).

Old symbol Address New symbol Evidence
FUN_0046f5a6 0x0046f5a6 lotr2_gfx_fill_iso_cell_rot0_edge0 param_3 * 0x101 fill; rot0 edge0 branch in lotr2_map_draw_cell_tile
FUN_0046f789 0x0046f789 lotr2_gfx_fill_iso_cell_rot0_edge2 rot0 edge2 (DAT_00582fe8 == 2)
FUN_0046f889 0x0046f889 lotr2_gfx_fill_iso_cell_rot0_edge1 rot0 edge1 (DAT_00582fe8 == 1)
FUN_0046f989 0x0046f989 lotr2_gfx_fill_iso_cell_rot1_edge0 rot1 edge0
FUN_0046fa8c 0x0046fa8c lotr2_gfx_fill_iso_cell_rot1_edge2 rot1 edge2
FUN_0046fb1c 0x0046fb1c lotr2_gfx_fill_iso_cell_rot1_edge1 rot1 edge1
FUN_0046fbac 0x0046fbac lotr2_gfx_fill_iso_cell_rot2_edge0 rot2 edge0
FUN_0046fc3f 0x0046fc3f lotr2_gfx_fill_iso_cell_rot2_edge2 rot2 edge2
FUN_0046fc97 0x0046fc97 lotr2_gfx_fill_iso_cell_rot2_edge1 rot2 edge1

Pass 41b — Map sprite row blit (scaled / unscaled)#

Old symbol Address New symbol Evidence
FUN_0046b141 0x0046b141 lotr2_gfx_blit_map_sprite_scaled Staggered dword copy from DAT_005fcf9c; caller lotr2_map_blit_map_sprite_scaled
FUN_0046b3dd 0x0046b3dd lotr2_gfx_blit_map_sprite_unscaled Offsets 0x280/0x500; caller lotr2_map_blit_map_sprite_unscaled
FUN_0046b51e 0x0046b51e lotr2_gfx_blit_map_sprite_scaled_alt Alt layout; caller lotr2_map_blit_map_sprite_alt
FUN_0046e782 0x0046e782 lotr2_gfx_blit_map_sprite_scaled_clip Scaled + param_4 clip gate
FUN_0046e846 0x0046e846 lotr2_gfx_blit_map_sprite_unscaled_clip Unscaled + clip gate
FUN_0046e8a2 0x0046e8a2 lotr2_gfx_blit_map_sprite_scaled_alt_clip Alt scaled + clip gate

Pass 41c — PL8 diagonal stamp loops#

Source _DAT_005ec398; row count DAT_005ae788; stride variants 0x282 / 0x2080 / 0xc80.

Old symbol Address New symbol Evidence
FUN_00460b44 0x00460b44 lotr2_gfx_stamp_pl8_diag_stride282 Diagonal loop; dest offsets 0x282
FUN_00461c18 0x00461c18 lotr2_gfx_stamp_pl8_diag_stride2080 Dest offsets 0x2080/0x1e02
FUN_00462ce9 0x00462ce9 lotr2_gfx_stamp_pl8_diag_stride2080_ext param_5 tail variant
FUN_00463e98 0x00463e98 lotr2_gfx_stamp_pl8_diag_stride282_ext param_5 + stride 0x282
FUN_0046b65c 0x0046b65c lotr2_gfx_stamp_pl8_diag_stridec80 Dest offsets 0xc80
FUN_0046be2f 0x0046be2f lotr2_gfx_stamp_pl8_diag_stride282_mirror stride282 mirror path
FUN_0046c263 0x0046c263 lotr2_gfx_stamp_pl8_diag_stridec80_mirror stridec80 mirror path
FUN_0046c694 0x0046c694 lotr2_gfx_stamp_pl8_diag_stridec80_ext param_5 + stridec80
FUN_0046cb3b 0x0046cb3b lotr2_gfx_stamp_pl8_diag_stride282_mirror_ext mirror + param_5

Pass 41d — PL8 row walk up backbuf (unrolled variants)#

Walk upward with -lotr2_gfx_backbuf_stride; used by combat message panel, UI text, build-queue paint, wizard config rows.

Old symbol Address New symbol Evidence
FUN_00464fb1 0x00464fb1 lotr2_gfx_stamp_pl8_rows_up_full Full unrolled row stamp from _DAT_005ec398
FUN_00466eb4 0x00466eb4 lotr2_gfx_stamp_pl8_rows_up_full_b Unrolled variant B
FUN_00467e21 0x00467e21 lotr2_gfx_stamp_pl8_rows_up_full_c Unrolled variant C
FUN_00468d8e 0x00468d8e lotr2_gfx_stamp_pl8_rows_up_stride282 Compact loop; offsets 0x282
FUN_00469f6d 0x00469f6d lotr2_gfx_stamp_pl8_rows_up_stride282_b stride282 variant B
FUN_0046cfb4 0x0046cfb4 lotr2_gfx_stamp_pl8_rows_up_compact Compact 6-byte source step
FUN_0046d6d7 0x0046d6d7 lotr2_gfx_stamp_pl8_rows_up_compact_b Compact variant B
FUN_0046da6c 0x0046da6c lotr2_gfx_stamp_pl8_rows_up_minimap Caller lotr2_game_ui_paint_minimap_pixels
FUN_0046de01 0x0046de01 lotr2_gfx_stamp_pl8_rows_up_stride282_c stride282 variant C
FUN_0046e2c8 0x0046e2c8 lotr2_gfx_stamp_pl8_rows_up_misc_pl8 Caller lotr2_game_load_misc_sel_pl8
FUN_0046e8fe 0x0046e8fe lotr2_gfx_stamp_pl8_rows_up_stride280 Dest offsets 0x280
FUN_0046ead1 0x0046ead1 lotr2_gfx_stamp_pl8_rows_up_stride282_d stride282 variant D
FUN_0046ebe5 0x0046ebe5 lotr2_gfx_stamp_pl8_rows_up_tail10 10-byte source tail
FUN_0046ecf6 0x0046ecf6 lotr2_gfx_stamp_pl8_rows_up_stride280_ext param_5 + stride280
FUN_0046ee49 0x0046ee49 lotr2_gfx_stamp_pl8_rows_up_stride282_ext param_5 + stride282
FUN_0046efa2 0x0046efa2 lotr2_gfx_stamp_pl8_rows_up_backbuf_clear Caller lotr2_gfx_clear_backbuf
FUN_0046f135 0x0046f135 lotr2_gfx_stamp_pl8_rows_up_clip_right Caller lotr2_gfx_blit_clip_right_row
FUN_0046f20e 0x0046f20e lotr2_gfx_stamp_pl8_rows_up_build_queue Build-queue rect paint path
FUN_0046f2e7 0x0046f2e7 lotr2_gfx_stamp_pl8_rows_up_wizard_cfg Wizard config value rows
FUN_0046f452 0x0046f452 lotr2_gfx_stamp_pl8_rows_up_wizard_hit Wizard config hit-test helper

Pass 42 — MSVC 6.0 debug CRT (0x4db000–0x4effff)#

Largest remaining FUN_* cluster before this pass (~380 refs in 0x4d–0x4e bands). Visual Studio 1998 Debug fingerprints: dbgheap.c, tzset.c, dbgrpt.c; __cexit/__cinit/__malloc_base call graph. Apply: tools/ghidra/crt_renames_pass42.py.

Pass 42a — String helpers#

Old symbol Address New symbol Evidence
FUN_004db1f0 0x004db1f0 crt_strlen Optimized uint* scan; used by path build + dbg report
FUN_004dda50 0x004dda50 crt_strcpy Optimized copy; callee of crt_getcwd_drive
FUN_004dda58 0x004dda58 crt_strcat Optimized append; sierra.ini path build in winmain

Pass 42b — Debug heap (dbgheap.c)#

Old symbol Address New symbol Evidence
FUN_004dc110 0x004dc110 crt_free Thin wrapper → crt_dbgheap_free(..., 1); 99 call sites
FUN_004dc130 0x004dc130 crt_dbgheap_free _CrtCheckMemory, block-type validate, _CheckBytes
FUN_004dbb20 0x004dbb20 crt_dbgheap_realloc __expand_dbg / _realloc_dbg body
FUN_004dcd00 0x004dcd00 crt_is_valid_heap_pointer __CrtIsValidPointer on block header; __CrtIsMemoryBlock
FUN_004dc6f0 0x004dc6f0 crt_set_dbg_heap_state Get/set DAT_005008c8; adjacent to __CrtSetDbgBlockType
FUN_004dc7c0 0x004dc7c0 crt_set_alloc_hook Get/set PTR_FUN_00501290 alloc hook
FUN_004dce50 0x004dce50 crt_set_break_alloc Get/set DAT_005ffac8 break-alloc id

Pass 42c — Process init / exit#

Old symbol Address New symbol Evidence
FUN_004db340 0x004db340 crt_do_exit Callee of __cexit / __c_exit; runs atexit, ExitProcess
FUN_004db420 0x004db420 crt_call_initterm Init/term function-pointer arrays; __cinit callee

Pass 42d — Win32 heap#

Old symbol Address New symbol Evidence
FUN_004de540 0x004de540 crt_malloc_retry_loop __malloc_base retry + __callnewh
FUN_004de5c0 0x004de5c0 crt_heap_alloc HeapAlloc(DAT_005ff960, …)
FUN_004dee70 0x004dee70 crt_heap_realloc_noserial HeapReAlloc flag 0x10
FUN_004deec0 0x004deec0 crt_realloc HeapReAlloc + new-handler loop
FUN_004def80 0x004def80 crt_heap_free HeapFree(DAT_005ff960, …)
FUN_004defb0 0x004defb0 crt_heap_validate HeapValidate; sets errno on failure
FUN_004df010 0x004df010 crt_heap_walk HeapLock / walk / validate loop
FUN_004df380 0x004df380 crt_heap_block_to_user Returns param_1 - 0x20 (header offset)
FUN_004e1630 0x004e1630 crt_heap_create HeapCreateDAT_005ff960
FUN_004e1660 0x004e1660 crt_heap_destroy HeapDestroy(DAT_005ff960)

Pass 42e — Path / time / debug report#

Old symbol Address New symbol Evidence
FUN_004dd620 0x004dd620 crt_getcwd GetCurrentDirectoryA wrapper
FUN_004dd650 0x004dd650 crt_getcwd_drive Drive letter + GetFullPathNameA
FUN_004dddd0 0x004dddd0 crt_localtime TZ bias + _gmtime / DST adjust
FUN_004ddff0 0x004ddff0 crt_time GetLocalTimecrt_mktime
FUN_004dfc00 0x004dfc00 crt_mktime Calendar → time_t + DST
FUN_004df790 0x004df790 crt_tzset_lazy One-shot guard → crt_tzset
FUN_004df7c0 0x004df7c0 crt_tzset GetTimeZoneInformation / TZ env
FUN_004dfa90 0x004dfa90 crt_tm_is_dst DST transition test for tm
FUN_004de460 0x004de460 crt_get_new_handler Returns DAT_00502adc
FUN_004de5f0 0x004de5f0 crt_debug_break DebugBreak()
FUN_004de740 0x004de740 crt_set_report_hook Get/set DAT_005ffab0
FUN_004dee50 0x004dee50 crt_report_hook_ok Report hook stub; returns 1
FUN_004deb30 0x004deb30 crt_dbg_report_messagebox crt_CrtDbgReport message-box worker
FUN_004e2770 0x004e2770 crt_trunc_module_path Truncates module path to 0x40 for report
FUN_004e17c0 0x004e17c0 crt_fatal_error R6002-style fatal; WriteFile to stderr

Pass 42f — CRT startup / lowio fd table#

Old symbol Address New symbol Evidence
FUN_004e0d80 0x004e0d80 crt_set_codepage getSystemCP / GetCPInfo / SBCS tables
FUN_004e1280 0x004e1280 crt_init_codepage Calls crt_set_codepage(0xfffffffd)
FUN_004e12a0 0x004e12a0 crt_ioinit Alloc/init DAT_005ff9b0 handle table
FUN_004dfdd6 0x004dfdd6 crt_seh_store_frame SEH unwind frame store for __local_unwind2
FUN_004e5d80 0x004e5d80 crt_get_osfhandle fd → Win32 handle via DAT_005ff9b0
FUN_004e5290 0x004e5290 crt_fd_is_textmode Text-mode bit from fd table entry
FUN_004e4900 0x004e4900 crt_flush_all_files _fflush all open FILE* slots
FUN_004e5b70 0x004e5b70 crt_set_osfhandle Bind handle to fd; SetStdHandle for 0–2

Pass 43 — combat battle-frame glue (0x004D4000–0x004DAFFF)#

Apply via tools/ghidra/combat_renames_pass43.py. Evidence: DAT_00502df8 battle tile cursor; DAT_00502da0 tile size 0x10/0x20; lotr2_combat_figure_* / lotr2_projectile_*; called from lotr2_game_main_frame_tick and lotr2_combat_tick_battle_screen.

Pass 43a — Grid init + main frame#

Old symbol Address New symbol Evidence
FUN_004d7020 0x004d7020 lotr2_combat_init_battle_grid_layout Sets DAT_00502ddc, stride, 80×80 dims; called from lotr2_combat_tick_battle_screen
FUN_004d7107 0x004d7107 lotr2_combat_init_battle_sprite_tables Sets DAT_00502de4/de8 sprite PL8 bases
FUN_004d49a0 0x004d49a0 lotr2_game_main_frame_tick Winmain per-frame loop; combat tick + viewport + present (distinct from lotr2_game_screen_tick @ 0x43a2e7)
FUN_004d6699 0x004d6699 lotr2_combat_advance_dirty_tile_timers timeGetTime; cycles DAT_005bc698 dirty flags
FUN_004d63d8 0x004d63d8 lotr2_combat_tick_battle_idle_state DAT_005ec49c idle; easter-egg exit / battle message enqueue
FUN_004d6479 0x004d6479 lotr2_combat_mp_frame_gate Debounced MP sync; calls lotr2_net_host_poll_sync_ready_loop

Pass 43b — Viewport orchestrator + terrain passes#

Old symbol Address New symbol Evidence
FUN_004d7142 0x004d7142 lotr2_combat_tick_battle_viewport Scroll origin; branches 0x10/0x20 tile modes; chains dirty + figure passes
FUN_004d71d1 0x004d71d1 lotr2_combat_advance_viewport_scroll Updates DAT_00502e08; calls scroll-row blit
FUN_004d751b 0x004d751b lotr2_combat_blit_viewport_scroll_rows Row walk DAT_00502df8; terrain/figure tile blit during scroll
FUN_004d78f0 0x004d78f0 lotr2_combat_blit_dirty_tiles_16px 16px mode; lotr2_gfx_blit_tile16_strip on dirty flag & 1
FUN_004d7bc4 0x004d7bc4 lotr2_combat_blit_dirty_tiles_16px_noop Empty stub (16px post-pass)
FUN_004d7bcf 0x004d7bcf lotr2_combat_blit_dirty_tiles_32px 32px mode full terrain + wall overlay blit
FUN_004d8071 0x004d8071 lotr2_combat_blit_siege_damage_tiles Siege damage layer; tile flag & 4; RLE blit via 004d0be7
FUN_004d8226 0x004d8226 lotr2_combat_blit_visible_figure_slots Iterates figure id byte 5; player visibility mask
FUN_004d8348 0x004d8348 lotr2_combat_mark_and_blit_viewport_delta Expanded viewport rect; terrain anim + markers + projectiles
FUN_004d8567 0x004d8567 lotr2_combat_blit_terrain_anim_tile Culture terrain cycle DAT_005643d2 + DAT_005818fc
FUN_004d874c 0x004d874c lotr2_combat_blit_map_marker_sprite Map markers 0x49/0x4c/0x61/100 → sprite index
FUN_004da1ec 0x004da1ec lotr2_combat_draw_debug_tile_numbers Debug overlay when DAT_005bc71c set

Pass 43c — Coordinate helpers#

Old symbol Address New symbol Evidence
FUN_004d7222 0x004d7222 lotr2_combat_point_in_battle_bounds Pixel pair inside scroll viewport
FUN_004d72a6 0x004d72a6 lotr2_combat_pixel_to_tile_x (x - db8) / da0
FUN_004d72c6 0x004d72c6 lotr2_combat_pixel_to_tile_y (y - dbc) / da0
FUN_004d72e6 0x004d72e6 lotr2_combat_pixel_to_cell_x_ceil Sub-tile cell X with dd8 bias
FUN_004d7347 0x004d7347 lotr2_combat_pixel_to_cell_x_floor Clamped to DAT_005035e8
FUN_004d73ad 0x004d73ad lotr2_combat_pixel_to_cell_y_ceil Sub-tile cell Y with dd8 bias
FUN_004d740e 0x004d740e lotr2_combat_pixel_to_cell_y_floor Clamped to DAT_005035e4
FUN_004d7472 0x004d7472 lotr2_combat_tile_x_delta Tile X distance between two pixel X
FUN_004d74bc 0x004d74bc lotr2_combat_tile_y_delta Tile Y distance between two pixel Y
FUN_004d7506 0x004d7506 lotr2_combat_get_tile_stride Returns DAT_00502da0 (16 or 32)

Pass 43d — Figure + projectile blit#

Old symbol Address New symbol Evidence
FUN_004d892b 0x004d892b lotr2_combat_build_figure_paint_list Collects in-view figures into DAT_00502e10
FUN_004d8a85 0x004d8a85 lotr2_combat_sort_figures_by_y Bubble-sort paint list by tile Y
FUN_004d8b88 0x004d8b88 lotr2_combat_blit_figures_back_to_front Y-sorted lotr2_combat_blit_figure_sprite per slot
FUN_004d8c24 0x004d8c24 lotr2_combat_blit_figure_sprite Walk anim offsets; infantry/siege sprite blit
FUN_004d9063 0x004d9063 lotr2_combat_blit_figure_headcount_label Head-count number sprites from DAT_005930d0
FUN_004d9332 0x004d9332 lotr2_combat_blit_build_queue_marker Siege build-queue icon + lotr2_map_paint_build_queue_rect
FUN_004d94d2 0x004d94d2 lotr2_combat_blit_peasant_figure_sprite Unit type 6 (peasant) alternate sprite path
FUN_004d97b1 0x004d97b1 lotr2_combat_blit_catapult_overlay_sprite Unit type 7 overlay from DAT_0059bc9c/9c354
FUN_004d9aac 0x004d9aac lotr2_combat_blit_trebuchet_fire_sprite Type 9 + state 0x0e fire frames
FUN_004d9ec7 0x004d9ec7 lotr2_combat_blit_projectile_chain Linked lotr2_projectile_* slots; arrow wobble

Pass 44 — campaign / economy cluster (0x456–0x5d2)#

Old symbol Address New symbol Evidence
FUN_00456c5a 0x00456c5a lotr2_game_calc_ai_tax_budget Army+food budget; callee of lotr2_game_ai_optimize_tax_rate
FUN_00456cf8 0x00456cf8 lotr2_game_calc_gold_food_budget Two-term gold+food budget variant (leaf)
FUN_00459285 0x00459285 lotr2_game_deduct_province_development_stock Deducts faction food/goods during province build; caller lotr2_game_resolve_capital_sieges
FUN_004593fe 0x004593fe lotr2_game_update_province_development_targets Updates growth targets/population tier after build progress check
FUN_0045956c 0x0045956c lotr2_game_calc_province_development_pct Completion percent from food/goods ratio vs targets
FUN_00459619 0x00459619 lotr2_game_recount_faction_developing_castles Scans map cells status 0x03; end-turn callee
FUN_00459709 0x00459709 lotr2_game_init_new_campaign_players New-game defaults for all players; calls allocation reset + prosperity
FUN_00459ab1 0x00459ab1 lotr2_game_reset_allocation_sliders_default Sets slider caps 0x21/0x32/0x11/100
FUN_00459b44 0x00459b44 lotr2_game_reset_allocation_sliders_limited Sets slider caps to 0xf; build/recruit UI callee
FUN_00459bd7 0x00459bd7 lotr2_game_recalc_allocation_sliders Recomputes all 8 allocation rows for local player
FUN_00459d83 0x00459d83 lotr2_game_allocation_slot_to_bucket Maps slot index via DAT_004f16c8; slot 0 war-goods override
FUN_00459df3 0x00459df3 lotr2_game_allocation_slot_enabled Returns whether allocation row is active
FUN_00459e5e 0x00459e5e lotr2_game_apply_allocation_slider_delta Clears + fills 25-byte row at DAT_00543560
FUN_00459f83 0x00459f83 lotr2_game_fill_allocation_slider_row Uniform fill of allocation slider row
FUN_0045a016 0x0045a016 lotr2_game_fill_allocation_slider_split Split fill across slider row (two tone values)
FUN_0045a173 0x0045a173 lotr2_game_refresh_minimap_overlay_colors Updates c3b1–c3b3 before lotr2_game_ui_paint_minimap_pixels
FUN_0045a4d3 0x0045a4d3 lotr2_game_advance_loading_anim_frame Cycles DAT_0059c890 0..0xf when DAT_005bc698 set
FUN_0045cb6d 0x0045cb6d lotr2_game_set_minimap_render_mode Sets DAT_0059344c minimap overlay mode flag
FUN_0045ce4b 0x0045ce4b lotr2_gfx_frame_hook_noop Empty stub; main frame tick hook
FUN_0045cf4f 0x0045cf4f lotr2_gfx_mark_dirty_tile64_dup 64×64 dirty rect; duplicate of lotr2_gfx_mark_dirty_tile64
FUN_0045cfa2 0x0045cfa2 lotr2_gfx_mark_dirty_tile80_dup 80×80 dirty rect; duplicate of lotr2_gfx_mark_dirty_tile80
FUN_0045cff5 0x0045cff5 lotr2_gfx_mark_dirty_tile96 96×96 dirty rect marker
FUN_0045d18a 0x0045d18a lotr2_gfx_dirty_hook_noop Empty stub between dirty-tile helpers
FUN_0045d22b 0x0045d22b lotr2_gfx_init_hook_noop Empty stub after lotr2_game_load_base_assets

Pass 45 — battle HUD + post-siege outcome (0x427–0x42a)#

Old symbol Address New symbol Evidence
FUN_00427fea 0x00427fea lotr2_game_ui_draw_battle_player_compare_rows 7 resource types × two player slots (stride 0x1a4); layout param 0/1/2; callee of outcome panels
FUN_00428715 0x00428715 lotr2_game_ui_draw_siege_field_battle_outcome_panel Screen mode 0x12; s080_*.wav; loads PL8; dual-player compare layout 0
FUN_004289ec 0x004289ec lotr2_game_ui_draw_siege_defender_routed_panel Screen mode 0x13; calls lotr2_game_battle_on_defender_routed; compare layout 1
FUN_00428c2d 0x00428c2d lotr2_game_ui_draw_battle_narrative_panel Screen mode 0x30; wrapped eng strings from DAT_0059c358 index
FUN_00428de3 0x00428de3 lotr2_combat_init_battle_hud_frame Screen modes 0x28/0x2c; status bar, viewport scroll, palette, present
FUN_00428f1c 0x00428f1c lotr2_combat_redraw_hud_resource_counters Food/gold centered numbers at (0x1fa,0x1a6) / (0x24a,0x1a6) when counts change
FUN_00429113 0x00429113 lotr2_combat_tick_hud_army_roster Battle screen modes 0x280x2f; refreshes roster when DAT_00582df0 changes
FUN_00429292 0x00429292 lotr2_combat_blit_hud_roster_icons Blits unit-type sprites for active side (DAT_00580bac) onto HUD strip
FUN_004293af 0x004293af lotr2_combat_draw_hud_roster_headcounts Head-count number fields beside roster icon positions
FUN_00429527 0x00429527 lotr2_combat_draw_paused_overlay Drawn when DAT_0059b858 set during battle (lotr2_game_main_frame_tick)
FUN_0042957c 0x0042957c lotr2_net_draw_mp_sync_debug_overlay MP session: Running/Paused, packet counters, divergence stats
FUN_00429a1f 0x00429a1f lotr2_net_draw_mp_object_leak_report Host leak report: Counties/Players/Pieces or Figures/Arrows/Groups
FUN_0042a098 0x0042a098 lotr2_combat_tick_dumb_view_banner DUMB VIEW ON banner when DAT_0059bcb4 set
FUN_0042a146 0x0042a146 lotr2_combat_draw_debug_hud_stats Debug sync counters at (0x1e0,200) during battle frame tick
FUN_0042a235 0x0042a235 lotr2_combat_draw_debug_figure_inspector Selected figure map/target/state dump when DAT_0055a8a8
FUN_0042abb8 0x0042abb8 lotr2_net_draw_debug_byte_dump Hex byte dump from DAT_00582f18 when DAT_0055aa2c
FUN_0042ace1 0x0042ace1 lotr2_game_ui_draw_intro_chapter_dialog Screen mode 0x44; eng sheet 0x59; DAT_00582d6c intro Smacker index

Pass 47a — gfx text / glyph blit tail (0x004d02xx)#

Apply: tools/ghidra/game_gfx_text_renames_pass47.py.

Old symbol Address New symbol Evidence
FUN_004d020e 0x004d020e lotr2_gfx_text_advance_packed_ptr Packed eng-string skip; callee of lotr2_game_ui_draw_eng_string
FUN_004d026b 0x004d026b lotr2_gfx_blit_glyph_pair_2x16 Two ushort rows into backbuf at lotr2_gfx_blit_origin_*
FUN_004d0be7 0x004d0be7 lotr2_gfx_blit_tile24_block 24-row tile block; campaign UI thunk_ callers
FUN_004d179c 0x004d179c lotr2_gfx_copy_backbuf_16rows_to_vram 16×4-dword rows from backbuf to param_2 + 0xa0000
FUN_004d18e8 0x004d18e8 lotr2_gfx_copy_backbuf_rows_to_vram Row-count variant of 16-row copy
FUN_004d1929 0x004d1929 lotr2_gfx_read_widget_rect_from_backbuf 3×8 row read from blit origin into buffer
FUN_004d19c6 0x004d19c6 lotr2_gfx_write_widget_rect_to_backbuf Inverse of read_widget_rect
DAT_005fcf9c 0x005fcf9c lotr2_gfx_glyph_src_base Source offset added to glyph/tile blit params
DAT_005bc6a4 0x005bc6a4 lotr2_gfx_blit_origin_x Backbuf X origin for text/tile blits
DAT_005bc6a8 0x005bc6a8 lotr2_gfx_blit_origin_y Backbuf Y origin (× stride)
DAT_005fcf7c 0x005fcf7c lotr2_gfx_text_line_count Outer loop in text advance
DAT_005bc722 0x005bc722 lotr2_gfx_text_char_skip Per-line character skip width
FUN_00432ee1 0x00432ee1 lotr2_map_nop_stub Empty stub (deferred)
FUN_00435d10 0x00435d10 lotr2_video_nop_stub Empty stub (deferred)
FUN_0043abfd 0x0043abfd lotr2_game_ui_nop_stub_abfd Empty stub (deferred)
FUN_0043ac0f 0x0043ac0f lotr2_game_ui_nop_stub_ac0f Empty stub (deferred)
FUN_0043ad6f 0x0043ad6f lotr2_game_ui_nop_stub_ad6f Empty stub (deferred)

Pass 47b — turn-phase flags + map cell base#

Apply: tools/ghidra/game_state_renames_pass47.py. Struct: docs/structs/lotr2_game_state.md.

Old symbol Address New symbol Evidence
DAT_0059b87c 0x0059b87c lotr2_game_turn_phase1_ack Toggled by lotr2_game_action_turn_phase1_toggle
DAT_0059b880 0x0059b880 lotr2_game_turn_phase2_ack Toggled in lotr2_game_action_end_turn
DAT_0059b884 0x0059b884 lotr2_game_turn_phase3_ack Phase 3 toggle; map entity PL8 vs sprite encoding
DAT_0059b8a4 0x0059b8a4 lotr2_game_turn_phase4_ack Toggled by lotr2_game_action_turn_phase4_toggle
DAT_0059b86c 0x0059b86c lotr2_game_ui_action_slots_active UI slot gate; lotr2_game_action_toggle_ui_slots
DAT_0059b870 0x0059b870 lotr2_game_map_scroll_lock Scroll lock; lotr2_game_action_toggle_map_scroll_lock
DAT_0059b874 0x0059b874 lotr2_game_wizard_panel_dirty Wizard panel refresh flag
DAT_0059b868 0x0059b868 lotr2_game_settings_opt_flag_a Settings menu on/off string variant
DAT_0059b82c 0x0059b82c lotr2_game_settings_opt_flag_b Settings menu on/off string variant
DAT_0055a6c4 0x0055a6c4 lotr2_game_map_entity_draw_token Map column entity draw scratch
DAT_00552180 0x00552180 lotr2_map_province_cell 64×64 province cell table base (8-byte stride)
lotr2_game_action_toggle_flag_b87c 0x0043c087 lotr2_game_action_turn_phase1_toggle Semantic rename (was DAT-address name)
lotr2_game_action_toggle_flag_b884 0x0043c1c4 lotr2_game_action_turn_phase3_toggle Semantic rename
lotr2_game_action_toggle_flag_b8a4 0x0043c23e lotr2_game_action_turn_phase4_toggle Semantic rename
lotr2_game_action_toggle_flag_b86c 0x0043c2b8 lotr2_game_action_toggle_ui_slots Semantic rename
lotr2_game_action_toggle_flag_b870 0x0043c2f8 lotr2_game_action_toggle_map_scroll_lock Semantic rename
lotr2_game_action_toggle_flag_b874 0x0043c7d3 lotr2_game_action_toggle_wizard_panel Semantic rename
lotr2_game_action_toggle_flag_b868 0x0043c606 lotr2_game_action_toggle_settings_opt_a Semantic rename
lotr2_game_action_toggle_flag_b82c 0x0043c5cb lotr2_game_action_toggle_settings_opt_b Semantic rename

Pass 48 — CRT tail + game/UI noop cleanup#

Subsystem picked: game (~885 lotr2_game_* defs, largest cluster of hex-suffix placeholder names). Also clears the last 8 active FUN_* (MSVC CRT @ 0x4e*).

CRT startup / lowio (last FUN_*)#

Old symbol Address New symbol Evidence
FUN_004e02a0 0x004e02a0 crt_build_environ_array CRT startup after __setargv; splits DAT_00500ff4 env block
FUN_004e0b30 0x004e0b30 crt_get_environment_strings GetEnvironmentStringsW/A; called from entry()
FUN_004e1260 0x004e1260 crt_get_codepage Returns DAT_0050187c (current ANSI code page)
FUN_004e1a60 0x004e1a60 crt_report_assertion Assertion-failed message box; handler.cpp string ref
FUN_004e4760 0x004e4760 crt_strncat Bounded append in assertion message build
FUN_004e55e0 0x004e55e0 crt_flush_osfhandle FlushFileBuffers for fd; _fflush path
FUN_004e5c70 0x004e5c70 crt_close_osfhandle Clears fd-table handle; _close path
FUN_004e6f50 0x004e6f50 crt_strchr SBCS strchr; __mbschr when code page is 0

UI callback stubs#

Old symbol Address New symbol Evidence
lotr2_ui_noop_519 0x004cc519 lotr2_ui_frame_tail_hook Battle frame tail; diplomacy redraw callees
lotr2_ui_noop_8cb 0x004cc8cb lotr2_ui_spin_step_a lotr2_ui_spin_delay_combo sequence
lotr2_ui_noop_8d6 0x004cc8d6 lotr2_ui_spin_step_b lotr2_ui_spin_delay_a loop body
lotr2_ui_noop_8e1 0x004cc8e1 lotr2_ui_spin_step_c lotr2_ui_spin_delay_b loop body
lotr2_ui_noop_7de 0x004cc7de lotr2_ui_callback_noop_a Dead stub cluster @ 0x4cc7xx
lotr2_ui_noop_006 0x004cc006 lotr2_ui_callback_noop_b Dead stub
lotr2_ui_noop_011 0x004cc011 lotr2_ui_callback_noop_c Dead stub
lotr2_ui_noop_01c 0x004cc01c lotr2_ui_callback_noop_d Dead stub

Turn-action table reserved slots (game)#

Old symbol Address New symbol Evidence
lotr2_game_wizard_noop_b844 0x0043b844 lotr2_game_wizard_noop_reserved Empty wizard table slot
lotr2_game_action_noop_c75ac7c8 0x0043c75a–0x0043c7c8 lotr2_game_action_noop_reserved_01_11 Empty slots after toggle_hicolor
lotr2_game_action_noop_c87bc911 0x0043c87b–0x0043c911 _12_14 Empty toolbar/overlay slots
lotr2_game_action_noop_cab7 0x0043cab7 _15 Empty slot before ui_message_yield
lotr2_game_action_noop_ccd4cdac 0x0043ccd4–0x0043cdac _16_19 Empty diplomacy/replay slots
lotr2_game_action_noop_d2cc 0x0043d2cc _20 Empty slot before replay-speed setters

Pass 51 — game turn-actions + state globals#

Apply: tools/ghidra/game_renames_pass51.py. Struct: docs/structs/lotr2_game_state.md.

Turn-action semantic names (0x43c cluster)#

Old symbol Address New symbol Evidence
lotr2_game_action_enter_mode_0x39 0x0043c023 lotr2_game_action_enter_options_dialog Sets mode '9'; draw callee lotr2_game_ui_draw_options_dialog; MP client sends deferred msg 0xe3
lotr2_game_action_enter_mode_0x0b 0x0043db3d lotr2_game_action_enter_diplomacy_faction_dialog Sets mode 0x0b; draw callee lotr2_game_ui_draw_diplomacy_faction_dialog; turn phase 5 dispatch
lotr2_game_action_enter_mode_0x42 0x0043c49d lotr2_game_action_enter_game_options_dialog Sets mode 'B'; draw callee lotr2_game_ui_draw_game_options_dialog
lotr2_game_action_enter_mode_0x43 0x0043c4b9 lotr2_game_action_enter_display_options_dialog Sets mode 'C'; draw callee lotr2_game_ui_draw_display_options_dialog
lotr2_game_action_mp_send_0x123 0x0043c33d lotr2_game_mp_send_toolbar_context_panel_0 lotr2_combat_enqueue_battle_message(…,0x123,…,0x13,…); panel slot msg_id - 0x123
lotr2_game_action_mp_send_0x124 0x0043c37b lotr2_game_mp_send_toolbar_context_panel_1 Same pattern; slot 1
lotr2_game_action_mp_send_0x125 0x0043c3b9 lotr2_game_mp_send_toolbar_context_panel_2 Same pattern; slot 2
lotr2_game_action_mp_send_0x126 0x0043c3f7 lotr2_game_mp_send_toolbar_context_panel_3 Same pattern; slot 3
lotr2_game_action_mp_send_0x127 0x0043c435 lotr2_game_mp_send_toolbar_context_panel_4 Same pattern; slot 4

High-traffic game / UI / map globals#

Old symbol Address New symbol Evidence
DAT_00580bac 0x00580bac lotr2_game_local_player_slot Player record stride 0x160; join payload field; protocol doc
DAT_0059c220 0x0059c220 lotr2_game_active_view 0=campaign map, 2=battle; assigned in battle enter/exit; gates click dispatch
DAT_005042cc 0x005042cc lotr2_ui_mouse_x Compared in lotr2_ui_hit_test_point / scroll-bar hit tests
DAT_005042d0 0x005042d0 lotr2_ui_mouse_y Paired with lotr2_ui_mouse_x
DAT_005934e0 0x005934e0 lotr2_map_tile_index_grid 0x81×0x41 dword grid; lotr2_map_paint_visible_grid, entity draw
DAT_0059c374 0x0059c374 lotr2_game_province_cell_scan_index Linear index (+8/iter) in lotr2_map_locate_province_structures

Pass 51c — follow-on batches (planned)#

Cluster Approx. count Next step
lotr2_game_ui_draw_* ~200 Group by lotr2_game_ui_draw_screen_widgets mode callee
lotr2_game_wizard_draw_* ~35 Tie to lotr2_game_wizard_step values
Letter-suffix variants (*_a/*_b) ~30 Diff SP vs MP paths before merge rename
DAT_0059xxxx block ~500 refs Struct recovery after anchors from pass 51

Pass 52 — DAT globals (AI turn, net join, UI scratch)#

Apply: tools/ghidra/dat_renames_pass52.py. Struct updates: docs/structs/lotr2_game_state.md, lotr2_net_msg_join.md, lotr2_net_msg_roster.md.

Game AI / economy#

Old symbol Address New symbol Evidence
DAT_0055abd0 0x0055abd0 lotr2_game_ai_turn_phase Outer sim phase 1–7; lotr2_game_ai_turn_phase_tick switch; advanced by lotr2_game_ai_advance_turn_phase
DAT_0055ada0 0x0055ada0 lotr2_game_ai_player_step Per-player inner step array (0–13, 999=done); reset by lotr2_game_ai_reset_step_counters
DAT_005643d0 0x005643d0 lotr2_game_army_record_table Army record base, stride 0x1a4; indexed throughout battle/economy code
DAT_00551e00 0x00551e00 lotr2_game_build_slot_index Build-queue scan cursor in lotr2_game_build_find_active_slot
DAT_005637e0 0x005637e0 lotr2_game_province_event_flags Event-popup layout bitmask in lotr2_game_ui_setup_province_event_chrome

Game UI scratch#

Old symbol Address New symbol Evidence
DAT_005f13e0 0x005f13e0 lotr2_game_ui_text_scratch Buffer passed to lotr2_game_ui_draw_eng_string / lotr2_game_ui_draw_text_run
DAT_005da4b4 0x005da4b4 lotr2_game_ui_draw_y_baseline Reset to 0 before each draw row; accumulates line Y offsets
DAT_005042c5 0x005042c5 lotr2_game_ui_modal_active Non-zero gates modal/dialog input in wndproc paths

Net join / roster#

Old symbol Address New symbol Evidence
DAT_0059b800 0x0059b800 lotr2_game_config_block 0x41c-byte block written to lords2.inf; 32-byte join name field
DAT_005da4b0 0x005da4b0 lotr2_net_join_flags Join-handshake payload field; set by lotr2_game_check_easter_egg
DAT_0055a8f4 0x0055a8f4 lotr2_net_assigned_slot Opcode 2 reply assigned-slot field
DAT_0055aca0 0x0055aca0 lotr2_net_session_setup_state Join reply + speed-preset setter
DAT_00580b98 0x00580b98 lotr2_net_roster_player_count Roster opcode 3 active player count

Combat / UI helpers#

Old symbol Address New symbol Evidence
DAT_0059c9e8 0x0059c9e8 lotr2_combat_tile_scan_x Nested loop column index in combat LOS tile scans
DAT_0059c9ec 0x0059c9ec lotr2_combat_tile_scan_y Nested loop row index (paired with above)
DAT_00505124 0x00505124 lotr2_ui_asset_scratch_ptr Realloc target of lotr2_ui_resize_scratch_buffer
DAT_00580450 0x00580450 lotr2_game_ui_toolbar_context_slot MP toolbar panel index; (value - 0x123) indexes layout table

Pass 53 — DAT globals (combat groups, difficulty, hover)#

Apply: tools/ghidra/dat_renames_pass53.py. Tracker: dat-rename-progress.md. Struct updates: docs/structs/lotr2_battle_group.md, docs/structs/lotr2_player_record.md, docs/structs/lotr2_game_state.md.

Combat groups#

Old symbol Address New symbol Evidence
DAT_00583140 0x00583140 lotr2_combat_group_table 0x34-byte slot table; lotr2_combat_alloc_group_slot / lotr2_combat_clear_group_slot
DAT_0055ab40 0x0055ab40 lotr2_combat_group_alloc_index Scan cursor 1..0x50 in lotr2_combat_alloc_group_slot
DAT_0055ab18 0x0055ab18 lotr2_combat_cur_group_index Group-order handlers index * 0x34 stride
DAT_0056432c 0x0056432c lotr2_combat_focus_group_index Spawn/group assign; arg to lotr2_combat_move_group_to_tile

Game difficulty / UI stats#

Old symbol Address New symbol Evidence
DAT_00583108 0x00583108 lotr2_game_great_noble_stat_column Column 0–5 switch in lotr2_game_ui_great_noble_stat_value
DAT_0059b8a8 0x0059b8a8 lotr2_game_difficulty_preset Campaign setup 0–3; input to lotr2_combat_sync_difficulty_flags
DAT_0059b888 0x0059b888 lotr2_game_culture_count (preset + 2) - lotr2_net_roster_player_count in difficulty sync

Combat hover / UI pointer#

Old symbol Address New symbol Evidence
DAT_00507754 0x00507754 lotr2_combat_hover_poll_time_ms timeGetTime throttle in lotr2_combat_poll_figure_hover; _DAT_ alias at same VA
DAT_00505348 0x00505348 lotr2_ui_pointer_input_dirty Set on mouse/button delta in lotr2_ui_poll_pointer_state
DAT_00507560 0x00507560 lotr2_combat_tooltip_blit_x Hover poll → lotr2_gfx_blit_origin_x
DAT_00507564 0x00507564 lotr2_combat_tooltip_blit_y Paired tooltip Y

Pass 54 — DAT globals (net roster payload slot bytes)#

Apply: tools/ghidra/dat_renames_pass54.py. Tracker: dat-rename-progress.md. Struct update: docs/structs/lotr2_net_msg_roster.md.

Wire-order slots 1–5 in opcode 3 payload (lotr2_net_pack_player_roster_sync / lotr2_net_unpack_player_roster_sync). Maps to campaign player slots 2–6 in memory (stride 0x160 from lotr2_game_ai_player_step region).

slot_flags_a[5] (player_record +0x06)#

Old symbol Address New symbol Evidence
DAT_0055af0a 0x0055af0a lotr2_net_roster_slot1_flags_a 1st byte in roster pack flags_a sequence
DAT_0055b06a 0x0055b06a lotr2_net_roster_slot2_flags_a 2nd byte; player slot 3 +0x06
DAT_0055b1ca 0x0055b1ca lotr2_net_roster_slot3_flags_a 3rd byte; player slot 4 +0x06
DAT_0055b32a 0x0055b32a lotr2_net_roster_slot4_flags_a 4th byte; player slot 5 +0x06
DAT_0055b48a 0x0055b48a lotr2_net_roster_slot5_flags_a 5th byte; spare slot +0x06

slot_flags_b[5] (player_record +0x01)#

Old symbol Address New symbol Evidence
DAT_0055af05 0x0055af05 lotr2_net_roster_slot1_flags_b 1st byte in roster pack flags_b sequence
DAT_0055b065 0x0055b065 lotr2_net_roster_slot2_flags_b 2nd byte; player slot 3 +0x01 (eliminated)
DAT_0055b1c5 0x0055b1c5 lotr2_net_roster_slot3_flags_b 3rd byte; player slot 4 +0x01
DAT_0055b325 0x0055b325 lotr2_net_roster_slot4_flags_b 4th byte; player slot 5 +0x01
DAT_0055b485 0x0055b485 lotr2_net_roster_slot5_flags_b 5th byte; spare slot +0x01

slot_ids[5] (display-name block +0x21)#

Old symbol Address New symbol Evidence
DAT_0055a951 0x0055a951 lotr2_net_roster_slot1_id 1st byte in roster pack slot_ids sequence
DAT_0055a97d 0x0055a97d lotr2_net_roster_slot2_id 2nd byte; name block slot 3 +0x21
DAT_0055a9a9 0x0055a9a9 lotr2_net_roster_slot3_id 3rd byte; name block slot 4 +0x21
DAT_0055a9d5 0x0055a9d5 lotr2_net_roster_slot4_id 4th byte; name block slot 5 +0x21
DAT_0055aa01 0x0055aa01 lotr2_net_roster_slot5_id 5th byte; name block slot 6 +0x21

Pass 55 — DAT globals (net roster player_ids, names, slot lookup)#

Apply: tools/ghidra/dat_renames_pass55.py. Tracker: dat-rename-progress.md. Struct update: docs/structs/lotr2_net_msg_roster.md.

Wire-order slots 1–5 in opcode 3 payload (lotr2_net_pack_player_roster_sync / lotr2_net_unpack_player_roster_sync). Name blocks are 0x14-byte fixed slices at stride 0x2c from display-name region 0x55a900. slot_to_player[6] base at 0x59bc20; unpack rebuilds lookup from nation-slot bytes.

player_ids[5] (DirectPlay id / slot data, uint32le)#

Old symbol Address New symbol Evidence
DAT_0055a92c 0x0055a92c lotr2_net_roster_player1_id 1st uint32 in roster pack player_ids sequence
DAT_0055a958 0x0055a958 lotr2_net_roster_player2_id 2nd uint32; name block slot 2 base +0x2c
DAT_0055a984 0x0055a984 lotr2_net_roster_player3_id 3rd uint32; name block slot 3
DAT_0055a9b0 0x0055a9b0 lotr2_net_roster_player4_id 4th uint32; name block slot 4
DAT_0055a9dc 0x0055a9dc lotr2_net_roster_player5_id 5th uint32; name block slot 5

player_names[5][0x14] (fixed 20-byte name blocks)#

Old symbol Address New symbol Evidence
DAT_0055a930 0x0055a930 lotr2_net_roster_player1_name 1st 0x14-byte block in roster pack
DAT_0055a95c 0x0055a95c lotr2_net_roster_player2_name 2nd block; follows player2_id
DAT_0055a988 0x0055a988 lotr2_net_roster_player3_name 3rd block
DAT_0055a9b4 0x0055a9b4 lotr2_net_roster_player4_name 4th block
DAT_0055a9e0 0x0055a9e0 lotr2_net_roster_player5_name 5th block

slot_to_player[6] (slot lookup bytes)#

Old symbol Address New symbol Evidence
DAT_0059bc20 0x0059bc20 lotr2_net_roster_slot_to_player 6-byte lookup; pack/unpack at payload +0x8b

Pass 56 — DAT globals (player display block @ 0x55a900)#

Apply: tools/ghidra/dat_renames_pass56.py. Tracker: dat-rename-progress.md. Struct update: docs/structs/lotr2_player_record.md.

Six 0x2c-byte blocks indexed by player slot 0–5. Slot-0 Ghidra anchors; all slots use base + slot * 0x2c. Name text starts at 0x55a904 (+0x04 from block base).

Old symbol Address New symbol Evidence
DAT_0055a900 0x0055a900 lotr2_game_player_display_id +0x00 uint32; DirectPlay id; stores elimination rank on defeat; thunk_lotr2_net_player_id_to_slot
DAT_0055a914 0x0055a914 lotr2_game_player_display_roster_scratch +0x14 byte; zeroed by pack/unpack roster sync post-loop
DAT_0055a925 0x0055a925 lotr2_game_player_display_nation_slot +0x25 byte; faction_color_copy; feeds slot_to_player rebuild in unpack
DAT_0055a926 0x0055a926 lotr2_game_player_display_custom_name +0x26 byte; non-zero skips nation-slot copy in unpack
DAT_0055a927 0x0055a927 lotr2_game_player_display_defeated +0x27 byte; set by lotr2_game_ai_mark_player_defeated; cleared by lotr2_game_ai_clear_player_human_flag

Pass 57 — DAT globals (player record identity @ 0x55ada4)#

Apply: tools/ghidra/dat_renames_pass57.py. Tracker: dat-rename-progress.md. Struct: docs/structs/lotr2_player_record.md.

352-byte player slots indexed by player_id * 0x160. Slot-0 Ghidra anchors.

Old symbol Address New symbol Evidence
DAT_0055ada4 0x0055ada4 lotr2_game_player_active +0x00; set when slot joins campaign; paired with eliminated in UI/diplomacy
DAT_0055ada5 0x0055ada5 lotr2_game_player_eliminated +0x01; wizard roster dims slot; lotr2_game_ai_mark_player_defeated
DAT_0055ada7 0x0055ada7 lotr2_game_player_culture_row +0x03; noble archetype 1–4; AI tables at (row*3-3)*0x50
DAT_0055ada8 0x0055ada8 lotr2_game_player_text_color_a +0x04; from 0x004f7cd6[faction_color*2] in assign-nation
DAT_0055ada9 0x0055ada9 lotr2_game_player_text_color_b +0x05; from 0x004f7cd7[faction_color*2]
DAT_0055adaa 0x0055adaa lotr2_game_player_faction_color +0x06; wizard color 1–5; copied to display block nation slot
DAT_0055adac 0x0055adac lotr2_game_player_avg_happiness +0x08; mean province c3bc in lotr2_game_ai_aggregate_player_province_stats

Pass 58 — DAT globals (player record stats @ 0x55adb0)#

Apply: tools/ghidra/dat_renames_pass58.py. Tracker: dat-rename-progress.md. Struct: docs/structs/lotr2_player_record.md.

352-byte player slots indexed by player_id * 0x160. Slot-0 Ghidra anchors for Great Noble counters refreshed by lotr2_game_ai_aggregate_player_province_stats.

Old symbol Address New symbol Evidence
DAT_0055adb0 0x0055adb0 lotr2_game_player_total_province_gold +0x0c; sum province c3d4; Great Noble col 5; score += value/10
DAT_0055adb4 0x0055adb4 lotr2_game_player_avg_province_gold +0x10; total gold / county count in aggregate
DAT_0055adb8 0x0055adb8 lotr2_game_player_total_gold_prev +0x14; snapshot of total gold before aggregate zero
DAT_0055adc8 0x0055adc8 lotr2_game_player_build_level_sum +0x24; sum province c3c6 in lotr2_game_sum_faction_build_levels
DAT_0055adc9 0x0055adc9 lotr2_game_player_county_count +0x25; owned province count; Great Noble col 0
DAT_0055adca 0x0055adca lotr2_game_player_popularity_peak +0x26; max county count seen; popularity tier messages
DAT_0055adcb 0x0055adcb lotr2_game_player_rank_tier +0x27; score rank 1–5 from lotr2_game_ai_compute_player_rankings
DAT_0055adcc 0x0055adcc lotr2_game_player_army_count +0x28; active army count in aggregate loop
DAT_0055adec 0x0055adec lotr2_game_player_castle_count +0x48; provinces with castle building (c570); Great Noble col 1
DAT_0055adf0 0x0055adf0 lotr2_game_player_score +0x4c; composite score; bubble-sorted for rank tier
DAT_0055adf4 0x0055adf4 lotr2_game_player_troop_total +0x50; sum army head_count; Great Noble col 2
DAT_0055adf8 0x0055adf8 lotr2_game_player_avg_province_pop +0x54; mean province c3bb (population); score += value*2
DAT_0055ae00 0x0055ae00 lotr2_game_player_county_ratio_pct +0x5c; county count as % of map total; score += value*10

Pass 59 — DAT globals (player AI/diplomacy @ 0x55adbc)#

Apply: tools/ghidra/dat_renames_pass59.py. Tracker: dat-rename-progress.md. Struct: docs/structs/lotr2_player_record.md.

352-byte player slots indexed by player_id * 0x160. AI attack cadence, alliance state, build rotation, and troop-buy budgets for lotr2_game_ai_* planners.

Old symbol Address New symbol Evidence
DAT_0055adbc 0x0055adbc lotr2_game_player_attack_pending +0x18; set when AI declares war; cleared each sim step 0; blocks war-target pick
DAT_0055adbe 0x0055adbe lotr2_game_player_alliance_scratch +0x1a; zeroed on campaign init and alliance form/break (write-only in retail)
DAT_0055ade5 0x0055ade5 lotr2_game_player_attack_wait_counter +0x41; incremented in lotr2_game_ai_army_attack_plan; vs attack_patience @ 0x004f3b60
DAT_0055ade8 0x0055ade8 lotr2_game_player_war_target_player +0x44; set by lotr2_map_ai_pick_war_target_player; filters nearest attack province
DAT_0055adeb 0x0055adeb lotr2_game_player_staging_army_slot +0x47; army slot for lotr2_map_ai_pick_best_staging_army
DAT_0055aded 0x0055aded lotr2_game_player_castle_build_turns +0x49; per-turn castle build counter vs noble table @ 0x004f3bc8
DAT_0055ae0c 0x0055ae0c lotr2_game_player_build_rotation_index +0x68; 0–9 cycle in lotr2_game_ai_build_rotation_pass
DAT_0055ae10 0x0055ae10 lotr2_game_player_ai_buy_sword_budget +0x6c; summed from province c584; lotr2_game_ai_buy_resource_partial vs troop_sword_threshold
DAT_0055ae14 0x0055ae14 lotr2_game_player_ai_buy_bow_budget +0x70; vs troop_bow_threshold @ 0x004f3bc4
DAT_0055ae1c 0x0055ae1c lotr2_game_player_ai_buy_pike_budget +0x78; summed from province c580; vs troop_pike_threshold @ 0x004f3bc0
DAT_0055ae20 0x0055ae20 lotr2_game_player_alliance_candidate +0x7c; AI diplomacy pick before lotr2_game_ai_form_alliance
DAT_0055ae21 0x0055ae21 lotr2_game_player_alliance_partner +0x7d; mutual alliance partner id; cleared on break

Pass 60 — DAT globals (diplomacy matrix @ 0x55ae24)#

Apply: tools/ghidra/dat_renames_pass60.py. Tracker: dat-rename-progress.md. Struct: docs/structs/lotr2_player_record.md.

Per-foe diplomacy fields: (&lotr2_game_player_dipl_attitude)[foe * 0x10 + player * 0x160]. Campaign init sets attitude 5 for active slots (lotr2_game_campaign_init_players).

Old symbol Address New symbol Evidence
DAT_0055ae24 0x0055ae24 lotr2_game_player_dipl_attitude +0x80; signed -0x1e..0x1e; UI bar; war/trade/tribute deltas
DAT_0055ae25 0x0055ae25 lotr2_game_player_dipl_allied +0x81; pairwise allied flag in lotr2_game_ai_form_alliance / break_alliance
DAT_0055ae26 0x0055ae26 lotr2_game_player_dipl_ai_alliance_score +0x82; AI alliance pressure counter; debug UI when DAT_0055c378
DAT_0055ae27 0x0055ae27 lotr2_game_player_dipl_war_escalation +0x83; 0→3 escalation before at_war in attitude-delta path
DAT_0055ae28 0x0055ae28 lotr2_game_player_dipl_at_war +0x84; war icon vs alliance icon in wizard roster UI
DAT_0055ae29 0x0055ae29 lotr2_game_player_dipl_trade_tier +0x85; trade-request tier; bumped on diplomacy queue type 1
DAT_0055ae2c 0x0055ae2c lotr2_game_player_dipl_tribute_peak +0x88; dword max tribute gold; lotr2_game_ai_diplomacy_tribute_offer
DAT_0055ae30 0x0055ae30 lotr2_game_player_dipl_truce +0x8c; truce/peace UI sprite; set on diplomacy action enqueue
DAT_0055ae31 0x0055ae31 lotr2_game_player_dipl_contact_level +0x8d; starts 1 at init; scales gold transfer in diplomacy handlers

Pass 61 — DAT globals (AI turn scratch @ 0x55ae85)#

Apply: tools/ghidra/dat_renames_pass61.py. Tracker: dat-rename-progress.md. Struct: docs/structs/lotr2_player_record.md.

Per-player AI turn scratch beyond the diplomacy matrix. Cleared on campaign init (lotr2_game_campaign_init_players); refreshed each AI pass by province pickers and attack planners.

Old symbol Address New symbol Evidence
DAT_0055ae85 0x0055ae85 lotr2_game_player_ai_primary_province +0xe1; best attack province from lotr2_game_ai_pick_primary_secondary_provinces; feeds lotr2_game_ai_army_attack_plan
DAT_0055ae86 0x0055ae86 lotr2_game_player_ai_secondary_province +0xe2; secondary province from same picker; defender spawn reinforcement path
DAT_0055ae88 0x0055ae88 lotr2_game_player_ai_attack_army_slot +0xe4; staging army scratch in lotr2_game_ai_army_attack_plan; validated via lotr2_map_ai_validate_army_merge_target; debug UI @ 0x004eeb40
DAT_0055ae89 0x0055ae89 lotr2_game_player_ai_taunt_counter +0xe5; 0–7 turn counter in lotr2_game_ai_elimination_taunt_pass when county ratio > 0x27
DAT_0055ae8a 0x0055ae8a lotr2_game_player_ai_taunt_armed +0xe6; set after taunt counter rolls over; gates alternate taunt branch
DAT_0055ae8b 0x0055ae8b lotr2_game_player_ai_war_target_override +0xe7; copied to lotr2_game_player_war_target_player in lotr2_map_ai_pick_war_target_player; set on alliance break
DAT_0055ae8c 0x0055ae8c lotr2_game_player_ai_alliance_attempt_counter +0xe8; incremented when ally candidate picked; vs alliance_patience @ 0x004f3b4c; debug UI @ 0x004eeb50
DAT_0055ae8d 0x0055ae8d lotr2_game_player_sole_survivor_flag +0xe9; set when ranking pass finds sole active survivor; triggers crown battle message 0xc3

Note: byte at +0xe3 (0x55ae87) is zeroed at init but has no separate DAT_* symbol.

Pass 62 — DAT globals (combat visibility + player economy @ 0x55ae8e)#

Apply: tools/ghidra/dat_renames_pass62.py. Tracker: dat-rename-progress.md. Struct: docs/structs/lotr2_player_record.md.

Per-player combat fog mask and economy/upkeep fields beyond AI turn scratch. Cleared on campaign init; treasury and build pools seeded from scenario tables.

Old symbol Address New symbol Evidence
DAT_0055ae8e 0x0055ae8e lotr2_game_player_combat_visibility_mask +0xea; copied to figure flags in lotr2_combat_reveal_figures_in_rect; cleared in lotr2_combat_clear_side_figure_flags; gates headcount labels in lotr2_game_ui_draw_map_entities_layered
DAT_0054954a 0x0054954a lotr2_combat_figure_visibility_flags +0x0a in figure record (0x1b0 stride from 0x00549540); OR/AND with player mask; drawn in signed-value UI
DAT_0055aeb8 0x0055aeb8 lotr2_game_player_treasury_gold +0x114; starting gold from scenario; compared to army upkeep in lotr2_game_upkeep_check_faction_budgets; province overview UI; debited in lotr2_game_apply_resource_delta
DAT_0055ae9c 0x0055ae9c lotr2_game_player_upkeep_army_strength +0xf8; refreshed from lotr2_game_sum_faction_army_strength; compared to treasury for deficit messages
DAT_0055aec0 0x0055aec0 lotr2_game_player_build_reserve_1 +0x11c; build-queue slot 1 pool in lotr2_game_diplomacy_execute_slot; bow recruitment gate in lotr2_game_ai_set_troop_recruitment_targets; init default 0x32
DAT_0055aec8 0x0055aec8 lotr2_game_player_build_reserve_3 +0x124; build-queue slot 3 pool; capital setup overflow sink in lotr2_game_apply_remote_capital_setup; init default 0x32
DAT_0055aed0 0x0055aed0 lotr2_game_player_build_reserve_0 +0x12c; build-queue slot 0 pool; sword recruitment gate (< 100); init default 0x32
DAT_0055aed8 0x0055aed8 lotr2_game_player_troop_stock_total +0x134; sum of six lotr2_game_player_troop_stock entries in lotr2_game_sum_faction_build_totals; AI defender spawn budget check
DAT_0055aedc 0x0055aedc lotr2_game_player_province_build_target +0x138; six-dword template copied into faction build table by lotr2_game_faction_reset_build_templates_b
DAT_0055aee0 0x0055aee0 lotr2_game_player_troop_stock +0x13c; six-dword troop stock array; province overview UI; incremented in lotr2_game_finalize_army_turn
DAT_0055aef0 0x0055aef0 lotr2_game_player_crown_total +0x14c; crown tally from army yields and events; win/desperation checks vs troop stock
DAT_0055aef8 0x0055aef8 lotr2_game_player_upkeep_warning_stage +0x154; 0→5 escalation in lotr2_game_upkeep_check_faction_budgets when treasury < army strength
DAT_0055aef9 0x0055aef9 lotr2_game_player_battle_msg_variant +0x155; 0→3 cycle indexing lotr2_combat_enqueue_battle_message string variants

Note: bytes at +0xeb..+0xec (0x55ae8f..0x55ae90) are zeroed at init but have no separate DAT_* symbols.

Pass 63 — DAT globals (treasury ledger scratch @ 0x55ae94)#

Apply: tools/ghidra/dat_renames_pass63.py. Tracker: dat-rename-progress.md. Struct: docs/structs/lotr2_player_record.md.

Per-player treasury shadow ledgers and diplomacy snapshot copies within the 0x160 player slot stride from lotr2_game_player_active.

Old symbol Address New symbol Evidence
DAT_0055ae94 0x0055ae94 lotr2_game_player_upkeep_tax_total +0xf0; incremented with treasury when lotr2_game_compute_build_upkeep credits province tax (0x55c46c); cleared on campaign init
DAT_0055ae98 0x0055ae98 lotr2_game_player_upkeep_tax_mirror +0xf4; parallel accumulator with upkeep_tax_total in build-upkeep pass; write-only in retail
DAT_0055aea4 0x0055aea4 lotr2_game_player_treasury_pay_ledger +0x100; paired with treasury debit when lotr2_game_apply_resource_delta spends gold on positive resource deltas
DAT_0055aea8 0x0055aea8 lotr2_game_player_treasury_pay_mirror +0x104; mirror of pay ledger incremented in same resource_delta branch
DAT_0055aeac 0x0055aeac lotr2_game_player_treasury_recv_ledger +0x108; paired with treasury credit on negative resource deltas in lotr2_game_apply_resource_delta
DAT_0055aeb0 0x0055aeb0 lotr2_game_player_treasury_recv_mirror +0x10c; mirror of recv ledger in same branch
DAT_0055aec4 0x0055aec4 lotr2_game_player_build_reserve_1_snapshot +0x120; copy of build_reserve_1 in lotr2_game_sync_faction_aggregates / diplomacy apply; read in lotr2_game_diplomacy_max_affordable when param_4 != 0
DAT_0055aed4 0x0055aed4 lotr2_game_player_build_reserve_0_snapshot +0x130; copy of build_reserve_0; diplomacy affordability for sword stock

GoG equivalents (DAT_0057bff4..DAT_0057c034) listed in dat_renames_pass63.py.

Note: treasury snapshot at +0x118 (0x55aebc) and build-reserve-3 snapshot at +0x128 (0x55aecc) use address literals only — no Ghidra DAT_* symbols.

Pass 64 — DAT globals (troop yield accumulators @ 0x55aee4)#

Apply: tools/ghidra/dat_renames_pass64.py. Tracker: dat-rename-progress.md. Struct: docs/structs/lotr2_player_record.md.

Per-player troop-yield pools (resource kinds 9 / 0xb / 0xd / 0xe) and faction upkeep rollup. Kind 0xc updates lotr2_game_player_troop_stock slot 0 (pass 62).

Old symbol Address New symbol Evidence
DAT_0055aee4 0x0055aee4 lotr2_game_player_troop_yield_res_b +0x140; resource kind 0xb in lotr2_game_apply_resource_delta; army yield short 0x00564540 in lotr2_game_finalize_army_turn; trade cost in lotr2_game_calc_build_turn_cost
DAT_0055aee8 0x0055aee8 lotr2_game_player_troop_yield_res_d +0x144; resource kind 0xd; army yield 0x00564542; trade UI when DAT_0059e620 == 0xd
DAT_0055aeec 0x0055aeec lotr2_game_player_troop_yield_res_9 +0x148; resource kind 9; army yield 0x00564544; bishop desperation +100 in lotr2_game_ai_apply_desperation_bonuses; defender spawn seeds 500
DAT_0055aef4 0x0055aef4 lotr2_game_player_troop_yield_res_e +0x150; resource kind 0xe; army yield 0x00564548; trade UI when DAT_0059e620 == 0xe
DAT_0055aefc 0x0055aefc lotr2_game_player_faction_upkeep_total +0x158; sum of province upkeep dwords (0x55c470) in lotr2_game_sum_faction_upkeep_totals; province overview UI (L2.ENG stat line 8)

GoG equivalents (DAT_0057c044..DAT_0057c05c) listed in dat_renames_pass64.py.

Pass 65 — save-field DAT globals (all 203 save blocks)#

Tracker: docs/spec/save/save-file-format.md.

Derived from analysis of all 203 save-file field blocks in the retail binary (0x004FA280 static field-pointer table). ~60 remaining scalars carry provisional lotr2_unk_* placeholders pending further call-site work. Confidence notes are in the spec file; high-confidence entries are grouped below by subsystem.

Province economy + map state#

Old symbol Address New symbol Evidence
DAT_0055c3b0 0x0055c3b0 lotr2_province_economy_table Base of economy array; [province_id * 0x300] stride in lotr2_game_economy_tick_player, lotr2_net_partial_checksum
DAT_00580bc0 0x00580bc0 lotr2_map_army_province_slots [slot * 4 + player * 0x50] in lotr2_map_build_army_slot_table; army cell index lookup
DAT_0055aa08 0x0055aa08 lotr2_map_selected_province [DAT_0055aa08 * 0x300] in province economy UI draw
DAT_0055aa20 0x0055aa20 lotr2_map_max_province_id Loop bound for (province_idx = 1; province_idx <= DAT_0055aa20; …)
DAT_0055ac6c 0x0055ac6c lotr2_map_viewport_row Clamped 0..0x40 in lotr2_map_clamp_viewport_origin
DAT_0055ac70 0x0055ac70 lotr2_map_viewport_col Clamped 0..0x80; used with lotr2_map_tile_index_grid
DAT_0055a898 0x0055a898 lotr2_map_iso_rotation if (DAT_0055a898 == 2) in lotr2_map_draw_cell_tile dispatch
DAT_0059344c 0x0059344c lotr2_map_minimap_mode lotr2_game_set_minimap_render_mode
DAT_0055b750 0x0055b750 lotr2_map_layer_province_lists [province + (layer-1) * 0x10] in lotr2_map_append_province_to_layer; 6 layers × 16 entries
DAT_00573bc0 0x00573bc0 lotr2_map_spawn_army_list lotr2_map_spawn_starting_armies_from_list, lotr2_map_build_layer_province_chains
DAT_0055ac00 0x0055ac00 lotr2_map_province_slot_pairs [player_id * 2] in lotr2_game_select_province_by_tile_index; starting province assignments
DAT_00582d34 0x00582d34 lotr2_map_province_slot_pair_count Incremented in lotr2_map_set_province_slot_pair
DAT_00563d50 0x00563d50 lotr2_map_province_build_costs Initialised from ROM table DAT_004f39f0; lotr2_map_init_province_cost_table
DAT_0059c34c 0x0059c34c lotr2_map_start_armies_spawned _DAT_0059c34c = _DAT_0059c34c + 1 in lotr2_map_spawn_starting_armies_from_list

Economy + diplomacy state#

Old symbol Address New symbol Evidence
DAT_0055bfcc 0x0055bfcc lotr2_econ_tick_phase lotr2_game_economy_tick_player(uVar2, DAT_0055bfcc); value 4 triggers special AI paths
DAT_005636e4 0x005636e4 lotr2_econ_tick_mode Snapshot of lotr2_econ_tick_phase taken at end-turn; lotr2_game_end_turn_tick
DAT_0059b7e4 0x0059b7e4 lotr2_diplomacy_tick_phase lotr2_game_diplomacy_tick_player(prov, DAT_0059b7e4)
DAT_0055c39c 0x0055c39c lotr2_econ_ui_flag Set to 1 in economy/province UI paths
DAT_0059c324 0x0059c324 lotr2_combat_battle_province lotr2_game_conquest_capture_province(…, DAT_0059c324); [DAT_0059c324 * 0x300] economy access
DAT_0059e620 0x0059e620 lotr2_econ_selected_resource lotr2_game_calc_build_turn_cost; values 0xD/0xE = trade resource types
DAT_0055c018 0x0055c018 lotr2_econ_province_dev_tier DAT_0055c018 = (byte)(&DAT_0055c5a9)[DAT_0059c324 * 0x300]; values 0–4
DAT_00582dac 0x00582dac lotr2_diplomacy_gold_offer Adjusted ±10, clamped to treasury; drawn and transmitted in diplomacy packet
DAT_0059c230 0x0059c230 lotr2_game_ai_diplomacy_queue [player_id * 0x28 + slot * 8] in lotr2_game_ai_process_diplomacy_queue; 6 × 5 slots × 8 B
DAT_0059c228 0x0059c228 lotr2_game_ai_diplomacy_cursor Indexes lotr2_combat_siege_entry_coords at stride 8

Turn / AI phase state#

Old symbol Address New symbol Evidence
DAT_0055ac48 0x0055ac48 lotr2_game_turn_number DAT_0055ac48 = DAT_0055ac48 + 1 in lotr2_game_end_turn_tick
DAT_0059bc28 0x0059bc28 lotr2_game_ai_turn_phase_prev _DAT_0059bc28 = lotr2_game_ai_turn_phase in lotr2_game_ai_advance_turn_phase
DAT_0055abd8 0x0055abd8 lotr2_game_ai_turn_phase_next DAT_0055abd8 = lotr2_game_ai_turn_phase + 1; if (7 < …) DAT_0055abd8 = 1
DAT_0059bfdc 0x0059bfdc lotr2_game_active_player_count Counted in lotr2_game_ai_reset_step_counters; compared ≥ 3 for minimum checks
DAT_0059b7f0 0x0059b7f0 lotr2_ranking_max_castle_player lotr2_game_ai_compute_player_rankings
DAT_0055a84c 0x0055a84c lotr2_game_ai_player_step_cursor lotr2_game_ai_player_step_loop
DAT_0059b85c 0x0059b85c lotr2_game_campaign_difficulty lotr2_game_economy_tick_player adds DAT_0059b85c * 0x14 to crown; values 0–3; loaded from difficulty config table
DAT_0059b88c 0x0059b88c lotr2_game_difficulty_param DAT_0059b88c = *(undefined4 *)(&DAT_004f7148 + DAT_0059b8ac * 4); cleared on battle UI init
DAT_0059b878 0x0059b878 lotr2_game_inf_load_count Load count index; DAT_0055a364 = *(uint *)(&DAT_004f3ef8 + DAT_0059b878 * 0x20)
DAT_0059e664 0x0059e664 lotr2_game_other_player_count Count of other active players; lotr2_game_ai_compute_player_rankings
DAT_005637cc 0x005637cc lotr2_game_event_province_cursor Random province cursor for event assignment; initialised 1 at new campaign
DAT_00507734 0x00507734 lotr2_game_screen_mode_saved lotr2_game_screen_mode = DAT_00507734 on load path

History ring#

Old symbol Address New symbol Evidence
DAT_0059bc3c 0x0059bc3c lotr2_history_write_slot Write cursor 0–399; if (399 < DAT_0059bc3c) DAT_0059bc3c = 0
DAT_0056433c 0x0056433c lotr2_history_ring_gen Wrap-generation counter; increments when ring overflows 400 entries
DAT_0059bcbc 0x0059bcbc lotr2_history_entry_count if (400 < DAT_0059bcbc) DAT_0059bcbc = 400

Battle figure array + recruit flags#

Old symbol Address New symbol Evidence
DAT_00549540 0x00549540 lotr2_combat_figure_slots [index * 0x1b0] stride in lotr2_combat_clear_all_figures, lotr2_net_partial_checksum
DAT_00582ff0 0x00582ff0 lotr2_recruit_flag_slots [slot * 0x14] stride in lotr2_combat_zero_flag_slot_bytes, lotr2_game_recruit_apply_flag_bonus

Battle combat state#

Old symbol Address New symbol Evidence
DAT_0055ac18 0x0055ac18 lotr2_combat_attacker_army_slot lotr2_game_army_record_table[DAT_0055ac18 * 0x1a4] in battle prep and resolution
DAT_0055ac1c 0x0055ac1c lotr2_combat_defender_army_slot Same pattern
DAT_0059c370 0x0059c370 lotr2_combat_is_siege if (DAT_0059c370 == 0) gates open-field vs siege spawn and order dispatch
DAT_0055ab70 0x0055ab70 lotr2_combat_attacker_strength DAT_00563e60 = (def + def/3 < DAT_0055ab70)
DAT_0055abe8 0x0055abe8 lotr2_combat_defender_strength DAT_0055f6c8 = (att + att/3 < DAT_0055abe8)
DAT_0055f6c8 0x0055f6c8 lotr2_combat_attacker_underdog 1 when attacker ≤75% of defender; passed to lotr2_combat_spawn_army_open_field
DAT_00563e60 0x00563e60 lotr2_combat_defender_underdog 1 when defender ≤75% of attacker; passed to siege and open-field spawn
DAT_0055c37c 0x0055c37c lotr2_combat_defender_troop_count Accumulated from defender figure head-counts; UI draw at coord 0x24a
DAT_00552154 0x00552154 lotr2_combat_attacker_troop_count Accumulated from attacker figure head-counts; UI draw at coord 0x1fa
DAT_0055c370 0x0055c370 lotr2_combat_defender_troop_snapshot _DAT_0055c370 = DAT_0055c37c in lotr2_combat_init_battle_state
DAT_0055b7b4 0x0055b7b4 lotr2_combat_attacker_troop_snapshot _DAT_0055b7b4 = DAT_00552154 in lotr2_combat_init_battle_state
DAT_0056437c 0x0056437c lotr2_combat_attacker_player_slot Set from attacker army record; default 6 = none
DAT_005643a8 0x005643a8 lotr2_combat_defender_player_slot Same pattern
DAT_0055c390 0x0055c390 lotr2_combat_attacker_owner Player id owning attacker army
DAT_0055c398 0x0055c398 lotr2_combat_defender_owner Player id owning defender army
DAT_0055aa14 0x0055aa14 lotr2_combat_battlefield_variant 0..0x2E; lotr2_combat_load_open_field_map
DAT_005814f4 0x005814f4 lotr2_combat_map_size_row Map-size row index for formation threshold lookup; lotr2_combat_init_battle_state
DAT_00563814 0x00563814 lotr2_combat_formation_shift_x Loaded from DAT_004f49a8[DAT_005814f4]; formation blit X-shift
DAT_00563820 0x00563820 lotr2_combat_formation_shift_y Loaded from DAT_004f49d0[DAT_005814f4]; formation blit Y-shift
DAT_0059c044 0x0059c044 lotr2_combat_prep_entered Flag set on entering battle prep; lotr2_game_action_enter_battle_prep
DAT_0055b748 0x0055b748 lotr2_combat_prep_ui_mode 1 = garrison empty, 2 = otherwise; set in battle army-pair validation
DAT_005934a0 0x005934a0 lotr2_combat_battlefield_variant_table 48 B permutation array; shuffled in lotr2_combat_reset_campaign_battle_state
DAT_0059bc44 0x0059bc44 lotr2_combat_battlefield_asset_pick DAT_0059bc44 = DAT_005934a0[DAT_0055aa14]
DAT_00581130 0x00581130 lotr2_combat_focus_group_table +(group-0x31)*4 + player*0x28; per-player focus-group index
DAT_0055acd0 0x0055acd0 lotr2_combat_siege_entry_coords [DAT_0059c228 * 8] in lotr2_combat_group_order_goto_siege_entry
DAT_00581230 0x00581230 lotr2_combat_siege_spawn_markers Cleared in lotr2_combat_parse_siege_spawn_markers
DAT_00563e70 0x00563e70 lotr2_combat_siege_sprite_slots [DAT_005818ec * 0x18] stride; lotr2_game_ui_memcpy_n
DAT_0055a6e0 0x0055a6e0 lotr2_combat_lane_coord_buf First-fit append in lotr2_combat_store_lane_coord; 19 × 8 B

Combat troop tallies (live per-tick)#

Old symbol Address New symbol Evidence
DAT_0055abc0 0x0055abc0 lotr2_combat_peasant_count Accumulated for unit type 0 in figure dirty-pass loop
DAT_0055ac34 0x0055ac34 lotr2_combat_archer_count Unit types 1 and 5
DAT_0054363c 0x0054363c lotr2_combat_idle_infantry_count Figure state = 0
DAT_0059c35c 0x0059c35c lotr2_combat_knight_count Unit type 6; lotr2_combat_assign_group_orders
DAT_0059bc78 0x0059bc78 lotr2_combat_catapult_count lotr2_combat_assign_group_orders
DAT_0059c3c8 0x0059c3c8 lotr2_combat_ram_count Same
DAT_00593460 0x00593460 lotr2_combat_siege_tower_count Same
DAT_005814f0 0x005814f0 lotr2_combat_moat_figure_count Same
DAT_00582d1c 0x00582d1c lotr2_combat_infantry_figure_count Non-siege infantry; same
DAT_00552150 0x00552150 lotr2_combat_gate_figure_count Figures on gate tiles (type 5, state 4); lotr2_combat_tick_all_figures
DAT_00581a00 0x00581a00 lotr2_combat_siege_engine_count Live siege-engine figures (types 7–9); same
DAT_00573bf4 0x00573bf4 lotr2_combat_moat_tile_type Tile type of current moat-digger; lotr2_combat_assign_group_orders
DAT_0059c390 0x0059c390 lotr2_combat_troop_compare_ui [type * 4] in lotr2_game_ui_draw_battle_player_compare_rows

Rankings#

Old symbol Address New symbol Evidence
DAT_00564340 0x00564340 lotr2_game_player_rankings Bubble-sorted 6-slot × 8 B table; lotr2_game_ai_compute_player_rankings
DAT_0055bfe4 0x0055bfe4 lotr2_ranking_top_player_id DAT_0055bfe4 = *(int *)(&DAT_00564340 + rank_slot * 8)
DAT_00593114 0x00593114 lotr2_ranking_top_player_id_b Set from same expression; distinct consumer
DAT_00573b8c 0x00573b8c lotr2_ranking_max_gold_val lotr2_game_ai_compute_player_rankings
DAT_00573ba4 0x00573ba4 lotr2_ranking_max_gold_player Same
DAT_0059c340 0x0059c340 lotr2_ranking_max_happiness_val Same
DAT_0059c360 0x0059c360 lotr2_ranking_max_happiness_player Same
DAT_0055ac60 0x0055ac60 lotr2_ranking_max_pop_val Same
DAT_0055ac90 0x0055ac90 lotr2_ranking_max_pop_player Same
DAT_00582dd0 0x00582dd0 lotr2_ranking_max_treasury_val Same
DAT_00582d64 0x00582d64 lotr2_ranking_max_treasury_player Same
DAT_005476bc 0x005476bc lotr2_ranking_max_county_player Same
DAT_0059e658 0x0059e658 lotr2_ranking_max_county_count Same
DAT_0059b7f0 0x0059b7f0 lotr2_ranking_max_castle_player Same (duplicate row in table above)
DAT_00593118 0x00593118 lotr2_ranking_max_castle_count Same
DAT_005819f0 0x005819f0 lotr2_ranking_max_troop_player Same
DAT_00581224 0x00581224 lotr2_ranking_max_troop_total Same
DAT_0055a780 0x0055a780 lotr2_ranking_max_army_val Same
DAT_0055a82c 0x0055a82c lotr2_ranking_max_army_player Same
DAT_005818e8 0x005818e8 lotr2_ranking_max_castle_val Same
DAT_005819d4 0x005819d4 lotr2_ranking_max_troop_val Same (provisional — confirm distinction from max_troop_total)

RNG + misc UI#

Old symbol Address New symbol Evidence
DAT_005da4b8 0x005da4b8 lotr2_rng_lfsr_hi Init 0x54657687; lotr2_game_rng_lfsr_shift_wide_pair
DAT_005da4bc 0x005da4bc lotr2_rng_lfsr_lo Init 0x72641663; same
DAT_00563850 0x00563850 lotr2_game_event_msg_table [i * 0xca] stride; lotr2_game_ui_draw_bytes_wrapped
DAT_0055a364 0x0055a364 lotr2_combat_ui_config DAT_0055a364 = *(uint *)(&DAT_004f3ef8 + DAT_0059b878 * 0x20)