Files
Sprinter-SDCC/applications/SprPoP/docs/keys_plan.md
T
snark13 659071838d SprPoP: KEYS-D, KEYS-R и KEYS-F12 — на доску отложенного
Три остатка плана 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>
2026-08-27 15:38:22 +03:00

171 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# План: перевод управления на раскладку `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 — делать ли их вообще: это читы и отладочный осмотр, к
прохождению игры отношения не имеющие.