# План: перевод управления на раскладку `keys.txt` Целевая раскладка — [`keys.txt`](keys.txt), она же раскладка SDLPoP. Здесь разобрано, что у нас уже есть, что стоит не на той клавише и каких функций нет вовсе, плюс порядок работ. Кода этот документ не меняет. ## 1. Принципы **Раскладка — не самоцель.** Часть строк `keys.txt` — это функции SDLPoP, которых у нас нет вообще (воскрешение, замедленное падение, осмотр соседних комнат). Поэтому работа делится на две разные по цене части: *переназначить клавишу* (минуты) и *реализовать функцию* (от часа до дня). Смешивать их в одной фазе нельзя — иначе простые переименования застрянут за сложным. **Механику сверять с SDLPoP.** Для каждой новой функции — сначала найти её в `assets/orig/SDLPoP/src/`, потом писать (правило проекта, memory `pop_check_sdlpop_first`). Особенно для читов: `Shift+S`/`Shift+T` — это не «прибавить HP», а конкретные `add_life`/`set_health_life`. **Кромка против удержания.** Игровые клавиши (стрелки, Shift) читаются как удержание — это held-state, ради которого и заводился ``. Все служебные и читерские — как НОВОЕ нажатие (edge), иначе одно касание сработает столько раз, сколько кадров клавиша была внизу. В коде уже есть оба образца: `read_user_control()` для первого, `intro_skip_requested()` и `hof_*` для второго. **Где живёт обработчик.** Служебный слой — `pop_frame_ui()` в `sprpop_cold.c` (банк 8), читы — `pop_cheat.h` + вызовы из главного цикла. После переноса `pop_config`/`pop_hof` в банк 10 в банке 9 свободно 4436 байт, в банке 8 — 1786; новые обработчики лучше класть в 8-й или 10-й, а не в 9-й. **Ctrl-комбинации уже поддержаны:** `Ctrl+S`/`Ctrl+M` проверяют `KBD_LCTRL || KBD_RCTRL` вместе с буквой (`sprpop_cold.c:518`). Тот же приём годится для `Ctrl+A`, `Ctrl+R`, `Ctrl+V`, `Ctrl+Q`, `Ctrl+B`. ## 2. Что есть сейчас ### Движение и бой — совпадает, кроме диагоналей | `keys.txt` | у нас | статус | |---|---|---| | Left / Right / Up / Down | стрелки, `read_input()` | **есть** | | Down+Left/Right — прыжок на месте | комбинация стрелок | **есть** | | Shift — поднять предмет | `KBD_LSHIFT`/`KBD_RSHIFT` | **есть** | | Shift+Left/Right — осторожный шаг | комбинация | **есть** | | Up+Left / Up+Right — прыжок в сторону | комбинация | **есть** | | **Home / Page Up** — то же самое | — | **НЕТ**: читаются только стрелки | | Up на бегу — прыжок с разбега | | **есть** | | Shift в падении — зацеп | | **есть** | | Бой: Left/Right/Shift/Up | | **есть** | | Бой: Down — убрать меч | | **проверить отдельно** | ### Служебные | `keys.txt` | у нас | статус | |---|---|---| | `Esc` — пауза/меню | `KBD_MENU = 0x76` | **есть** | | `Backspace` — меню | — | **НЕТ** (в оригинале это основная клавиша меню, Esc — дублёр) | | `Space` — показать остаток времени | — | **НЕТ** (`Space` занят только в меню и вводе имени) | | `Ctrl+A` — рестарт уровня | только пунктом меню | **НЕТ клавиши** | | `Ctrl+R` — вернуться в заставку | — | **НЕТ** | | `Ctrl+S` — звук вкл/выкл | `Ctrl+S` | **есть, совпадает** | | `Ctrl+M` — музыка вкл/выкл | `Ctrl+M` | **есть, совпадает** | | `Ctrl+V` — версия | `pop_build_info_show()` есть, зовётся на старте | **НЕТ клавиши** | | `Ctrl+Q` / `F10` — выход | `F10` в двух местах | **половина** (см. §3) | | `F6` / `F9` — quicksave/load | совпадает | **есть** | | `F12` — скриншот | — | помечено опциональным, **не делаем** | ### Читы | `keys.txt` | у нас | статус | |---|---|---| | `Shift+L` — следующий уровень | совпадает | **есть** | | `K` — убить стража | совпадает | **есть** | | `[` / `]` — сдвинуть Кида на пиксель | совпадает | **есть** | | `+` / `−` — минута времени | у нас это **F7/F8**, а `+`/`−` заняты обходом комнат | **конфликт, см. §3** | | `Shift+I` — перевернуть экран | у нас это **`U`** | **переназначить** | | `R` — воскресить Кида | — | **НЕТ функции** | | `Shift+W` — замедленное падение | — | **НЕТ функции** | | `Shift+S` — вернуть одну единицу HP | — | **НЕТ функции** | | `Shift+T` — добавить HP | — | **НЕТ функции** | | `T` — показывать таймер | — | **НЕТ функции** | ### Осмотр комнат — нет целиком `H` / `J` / `U` / `N` (соседняя комната слева/справа/сверху/снизу) и `Ctrl+B` (вернуться к Кида) не реализованы. У нас есть отладочный **обход комнат по номеру** (`+`/`−`, `ROOMNAV` в `sprpop.c`) — это другое: он ТЕЛЕПОРТИРУЕТ Кида, а `H/J/U/N` только смотрят, не двигая его. ### Наше сверх `keys.txt` `I` — бессмертие, `P` — режим скорости, `1`/`2` — стоп-кадр, `+`/`−` — обход комнат. Всё это отладочное и в оригинале отсутствует; выбросить или оставить — решение пользователя (§6). ## 3. Конфликты, которые надо решить до кодинга **К1. `+`/`−`: время или комнаты.** `keys.txt` отдаёт их под ±минуту, у нас на них обход комнат, а время висит на F7/F8. В `pop_cheat.h` это записано как осознанный выбор («Numpad +/- уже принадлежат ROOMNAV»). Варианты: вернуть `+`/`−` времени и увести ROOMNAV на другие клавиши; оставить как есть и разойтись с `keys.txt`; либо развести по контексту (ROOMNAV — только в отладочной сборке). Развилка требует решения. **К2. `U` занят.** Сейчас `U` — переворот экрана, а `keys.txt` хочет `U` под «посмотреть комнату сверху», переворот — на `Shift+I`. Разрешается само, если делать К5 и К7 одной фазой. **К3. `S` без Ctrl.** Звук у нас требует Ctrl, и это правильно, но `keys.txt` хочет ещё и `Shift+S` (вернуть HP). Проверка обязана различать `Ctrl+S`, `Shift+S` и голое `S`, иначе они будут срабатывать вместе. То же для `T`: `T` (таймер) против `Shift+T` (добавить HP). **К4. Два выхода.** `F10` живёт в `pop_frame_ui()` (только в игре) и, с коммита 808c2a5, в `kbd_idle()` (везде). Дублирование безвредное, но лишнее: проверку в `pop_frame_ui` стоит убрать, оставив одну точку. Заодно повесить туда же `Ctrl+Q`. ## 4. Порядок работ **Фаза A — переназначения, функции уже есть.** Дёшево и не трогает логику. - `Shift+I` вместо `U` для переворота экрана (К2). - `Backspace` как основная клавиша меню, `Esc` оставить дублёром. - `Ctrl+V` на существующий `pop_build_info_show()`. - `Ctrl+Q` рядом с `F10`, убрать дубль `F10` из `pop_frame_ui` (К4). - `Ctrl+A` на существующий путь `POP_MENU_RESTART_LEVEL`. - Решение по К1 и правка `+`/`−`/F7/F8. **Фаза B — мелкие новые функции.** - `Space` — показать остаток времени. Механика есть (`pop_timer`, статус- строка); нужен показ на несколько секунд, как `text_time_total` оригинала. - `T` — постоянный показ таймера (минуты:секунды) в статус-строке. - `Ctrl+R` — возврат в заставку. Автомат это умеет (`POP_APP_EV_RESTART_INTRO`), нужен только вход с клавиши. **Фаза C — читы, требующие правки игровой логики.** Каждый — сверка с SDLPoP до кодинга. - `Shift+S` / `Shift+T` — HP: аналоги малого и большого красного зелья. - `R` — воскрешение Кида: сложнее прочих, поднимает мёртвого персонажа и должен согласоваться с уже существующим гейтом «мёртв» (memory `pop_level_restart_scope`). - `Shift+W` — замедленное падение. **Фаза D — осмотр соседних комнат (`H`/`J`/`U`/`N` + `Ctrl+B`).** Самое крупное: нужен показ комнаты, в которой Кида нет, с возвратом. У нас уже разобрана модель `kid_room ≠ drawn_room` (memory `pop_seam_room_model`, [`room_model_plan.md`](room_model_plan.md)) — это её прямое применение, и именно поэтому фаза идёт последней. **Фаза E — `F12` скриншот.** Помечен опциональным; предлагаю не делать вовсе: файл на 80 КБ и запись на диск посреди кадра. ## 5. Открытые вопросы 1. **К1** — кому отдать `+`/`−`: времени (как `keys.txt`) или обходу комнат? 2. Что делать с нашими сверхштатными клавишами (`I` бессмертие, `P` скорость, `1`/`2` стоп-кадр): оставить как есть, увести под отладочную сборку или выбросить? 3. Нужны ли `Home`/`Page Up` как дублёры диагональных прыжков — на IBM-клавиатуре Sprinter они есть, но комбинация `Up+Left` уже работает. 4. Фазы C и D — делать ли их вообще: это читы и отладочный осмотр, к прохождению игры отношения не имеющие.