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_0x123–0x127 → 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 (00459285–0045956c),
new-campaign player init (00459709), allocation slider table (00459ab1–0045a016),
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 (0x00426000–0x00427fff) — 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 (0x0043b000–0x0043dfff) — 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 (0x0041f000–0x00425fff) — 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 (0x004c0000–0x004cffff) — 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 (0x0043e000–0x0044ffff) — 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_00493754 … FUN_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 |
| 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 0x449e00–0x44ee00 (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) |
| 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 |
| 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 |
See combat/MODULE.md.
| 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 |
Path cost grid / search
| 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 |
| 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 (0x480000–0x4affff)
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 |
0x481xxx–0x484xxx |
lotr2_combat_run_pathfind_search, lotr2_combat_pathfind_to_tile |
| Battle UI / messages |
0x484xxx–0x489xxx |
lotr2_combat_dispatch_queued_message, lotr2_combat_siege_ui_action_id |
| Session lifecycle |
0x48bxxx–0x48exxx |
lotr2_combat_set_battle_outcome_code, lotr2_combat_load_siege_field_map |
| Spawn / formation |
0x490xxx–0x492xxx |
lotr2_combat_spawn_army_open_field, lotr2_combat_spawn_figure_batch |
| Figure state machine |
0x494xxx–0x496xxx |
lotr2_combat_tick_figure_start_melee, lotr2_combat_tick_figure_chase_target |
| Group AI / orders |
0x499xxx–0x49fxxx |
lotr2_combat_tick_all_groups, lotr2_combat_group_order_goto_siege_entry |
| Targeting / LOS / projectiles |
0x4a4xxx–0x4a6xxx |
lotr2_combat_scan_adjacent_melee_target, lotr2_combat_probe_los_square |
| Battle screen |
0x4aexxx–0x4afxxx |
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 0x005841c2–0x005841c6.
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 (0x44ef1f–0x44f598)
34 function bodies at 0x0044ef1f–0x0044f598 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 (0x4065–0x458f)
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 (0x407–0x408)
| 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) |
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 (0x43b–0x43d)
| 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 (0x40d–0x413)
| 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 (0x451–0x458)
| 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 (0x405–0x409)
| 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 (0x747–0x7d2)
| 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 (0x748–0x7fb4)
| 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 (0x4e4d–0x4e6e)
| 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 (0x42fe–0x430f)
| 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 (0x4e7b–0x4e81)
| 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 (0x4069–0x406c)
| 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 (0x4092–0x4099)
| 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 (0x40a9–0x40b8)
| 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 (0x406d–0x40ca, 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 (0x417e–0x41a6)
| 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 (0x417–0x41f)
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
0x44ef1f–0x44f598 (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 (0x4c9f–0x4cce)
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 (0x4b0000–0x4bffff)
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 (0x43e000–0x44ffff)
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 0x23 → lotr2_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 0x36 → lotr2_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 |
| 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_004442b1–004444c2 |
0x004442b1… |
lotr2_game_ui_noop_* |
Empty/thunk padding cluster |
FUN_0044f17b–0044f598 |
0x0044f17b… |
lotr2_net_apply_remote_* |
Net unpack dispatch targets (thin apply wrappers) |
Pass 36 — castle / build / recruit (0x004c0000–0x004cffff)
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 (0x82–0x86) |
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 0xa0–0x111) |
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_004cede0–004cf2b2 |
0x004cede0… |
lotr2_game_play_*_sfx_* |
UI/battle WAV cue helpers (S010–S246 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_004cf774–004cfbe2 |
0x004cf774… |
lotr2_gfx_*_backbuf_* |
Castle-view software backbuf blit/fill helpers |
FUN_004c9000–004c9062 |
0x004c9000… |
lotr2_game_stub_* / lotr2_game_noop_* |
Empty vtable/stub slots |
FUN_004cec70–004cec86 |
0x004cec70… |
lotr2_game_noop_cec* |
Empty returns adjacent to intro hook |
Pass 37 — castle interior / gateway UI (0x41f000–0x425fff)
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 0x0d→0x0a 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.pl8…arm_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 (0x43b000–0x43dfff)
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 |
| 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 (0x426000–0x427fff)
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 |
| 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 |
HeapCreate → DAT_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 |
GetLocalTime → crt_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) |
| 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 0x28–0x2f; 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_c75a … c7c8 |
0x0043c75a–0x0043c7c8 |
lotr2_game_action_noop_reserved_01–_11 |
Empty slots after toggle_hicolor |
lotr2_game_action_noop_c87b … c911 |
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_ccd4 … cdac |
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 |
| 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) |