659071838d
Три остатка плана keys_plan.md записаны в TASKS_OPEN.md с полным разбором, чтобы не выводить его заново. KEYS-D (осмотр соседних комнат) — главное, что стоит помнить: у SDLPoP это три строки, потому что там drawn_room влияет ТОЛЬКО на отрисовку, а физика ходит через get_tile(room, col, row) с явной комнатой. У нас наоборот — карта коллизий грузится для ОТРИСОВАННОЙ комнаты: room_fg, lcol_fg, rcol_fg, above_fg, below_fg это ОДИН комплект на программу. Уведи cur_room к соседу, не трогая kid_room, и Кид считает столкновения по чужим тайлам. Задел под расхождение уже стоит (kid_room отдельной переменной, update_kid_render_dx со сдвигом ±140), но enter_room_side пишет обе разом — это незакрытая часть S3 straddle. Записаны оба пути с ценой: честный (правка ядра, дни) и смотровой режим с остановкой игры (150-250 байт, часы) — плюс что главный риск не в отрисовке, а в возврате. KEYS-R (воскрешение) — четыре места, которые обязаны знать про окно неуязвимости, со ссылками на seg-код. KEYS-F12 (скриншот) — «возможно, когда-то», по пометке пользователя. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
171 lines
12 KiB
Markdown
171 lines
12 KiB
Markdown
# План: перевод управления на раскладку `keys.txt`
|
||
|
||
> **Состояние на 2026-08-27.** Фазы **A** и **B** сделаны (коммит 76f02e7),
|
||
> фаза **C** — три чита из четырёх (f8e96c0). Отложены и записаны на доску
|
||
> [`TASKS_OPEN.md`](TASKS_OPEN.md): `KEYS-R` (воскрешение), `KEYS-D` (осмотр
|
||
> соседних комнат), `KEYS-F12` (скриншот). Итоговая раскладка, включая наши
|
||
> сверхштатные клавиши, — в [`keys.txt`](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, ради которого и заводился `<kbd_raw.h>`. Все
|
||
служебные и читерские — как НОВОЕ нажатие (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 — делать ли их вообще: это читы и отладочный осмотр, к
|
||
прохождению игры отношения не имеющие.
|