# Retail keyboard defaults and routing audit — 2026-08-26 ## Verdict The code gate for #446 now covers all 306 user-bindable rows in the installed Sept-2013 EoR ActionMap. Each row has a distinct `InputAction`, appears enabled in Configure Keyboard, persists through retail-compatible named `.keymap` profiles, and reaches a concrete subsystem consumer. The exact installed-DAT default chord set has zero exceptions. The remaining gate is a connected visual/behavior pass and a fresh-process persistence check. The approved acdream extension is deliberately retained: mouse-wheel chase zoom may pull back to 40 m. It does not change the retail keyboard defaults or the keypad camera actions. ## Oracles - `docs/research/named-retail/retail-default.keymap.txt` and installed `client_portal.dat` ActionMap DID `0x26000000`: the 306 rows, default chords, activation types, input contexts, and `ConflictingMaps` relationships. - Installed MasterInputMaps `0x14000000` and `0x14000002`: non-bindable system and mouse commands. - `ClientUISystem::OnAction @0x00564B90`: Escape priority. - `CInputManager_WIN32::GetNameFromKey_Internal @0x00687800` and `ControlNameMapper::LoadSemantics`: displayed keyboard/mouse names. - `ACCmdInterp::InitializeEmoteInputActionHash @0x0058B510`: all 87 emote action-to-motion mappings. - `CPlayerSystem::SelectNext @0x0055F9A0`: selection-cycle filtering and opened-corpse behavior. ## Exact ActionMap coverage | Retail input map | Rows | Consumer | |---|---:|---| | Movement | 14 | Runtime movement owner, including four postures | | Camera + alternate camera | 22 | Held camera input, presets, alternate-scope modifier, instant mouse look | | Combat + melee + missile + magic | 32 | Runtime combat attack owner and spellcasting controller, including spell slots 1–12 | | Emotes | 87 | Exact retail raw-motion table and Runtime `ExecuteMotion` | | Item selection | 26 | Selection controller/query and canonical inventory interaction state | | UI | 42 | Retained panels, screenshot, help/plugin result, logout, and selection commands | | Chat + chat-entry toggle | 7 | Retained chat entry/reply/command routes | | Quickslots | 28 | Toolbar use/select/create routes, including slots 10–18 | | Character settings | 48 | Exact `CharacterOptionId` bit toggle through Runtime | | **Total** | **306** | **306 distinct live identities** | The low MasterInputMap entries such as bare Escape and raw mouse event commands are intentionally not Configure Keyboard rows in retail and are not counted among the 306. Unknown rows from a future DAT can still round-trip in the compatibility sibling store, but the installed EoR DAT has no such row and shows no dimmed/store-only keyboard entry. ## Behavior completed - Defaults are an exact installed-DAT transcription, including bare `LeftShift`; device, modifier, activation, and scope all match. - Primary and alternate camera maps remain distinct rebind targets even where retail reuses an action id. The alternate modifier changes the active camera scope without aliasing saved bindings. - Same physical chord may fire each distinct retail action allowed by the ActionMap. In particular, the authored Alt+1..4 chat/UI and quickslot rows multicast instead of one silently replacing the other. - Rebind conflicts use the DAT `ConflictingMaps` table. The shared melee, missile, and magic key cluster remains legal; true conflicts still prompt. - Capture accepts keyboard keys, modifier-only bindings, and mouse buttons. Physical modifier self-bits are normalized, so binding LeftShift does not accidentally become Shift+LeftShift. Mouse button names use retail's `DIMOFS_BUTTON0..7` semantics table. Unsupported joystick and left/right mouse inputs keep the instruction dialog open and re-arm capture. - Setting the chord already present on the same row is a no-op. New chords use retail's dense two-slot insertion rule, and conflicts use priority dialogs with the exact installed-DAT singular/plural and non-bindable text. - Apply/OK, Revert, Defaults, Cancel, explicit unbinding, schema migration, and startup persistence are covered. Revert is enabled only while dirty; OK avoids rewriting an unchanged file. - Load File and Save As use retail's type-7 menu/type-5 text-entry dialogs, PFile bracket-text grammar, filename normalization, overwrite/read-only handling, `Documents\Asheron's Call\*.keymap` directory, selected-profile preference, startup load, and graceful-shutdown rewrite. The portable JSON file remains only as an acdream-host-command compatibility mirror. - Escape follows retail's priority: finish jump charge, release focused UI, stop movement/repeat attack, cancel target mode, clear selection, then toggle the authored Gameplay Options page. It never exits player mode or exposes the orbit/developer camera. Shift+Escape reaches the normal logout gate. - Selection cycling applies retail's containment, cloaking, radar, attackable, fellow, vendor, environment, combat-mode, and opened-corpse rules. Opened-corpse history lives for the session and retires on object deletion. - Screenshot, help, and plugin actions are consumed. Missing separately shipped retail help/plugin surfaces report an honest chat/system result rather than doing nothing. ## Automated verification - App: 6,413/6,413 passed. - Core: 4,713/4,713 passed. - Runtime: 1,849/1,849 passed. - UI.Abstractions: 879/879 passed. - Installed-DAT identity/default conformance and the authored Configure Keyboard mount pin all 306 rows. The `.keymap` codec parses the committed real retail file and round-trips all 306 user-bindable identities, including low-bit Shift/Ctrl/Alt/Win modifiers, DirectInput controls, fixed Escape/system/edit/pointer maps, and the 48 CharacterOption action names. AP-202 is retired. The connected gate could not be run because no local ACE endpoint was listening on UDP port 9000. ## Connected acceptance gate Use the installed EoR DATs and the normal owner-gate pak. In Configure Keyboard, verify that all rows are enabled and that a key, modifier-only chord, and mouse button can each be rebound. Exercise representative movement, camera, melee/missile/magic, emote, selection, panel, chat, quickslot, and character-option actions. Verify conflict prompt, Cancel, Revert, Defaults, Apply, and OK, then restart the process and confirm the applied bindings remain.