SprPoP: раскладка управления — фазы A и B плана keys_plan.md
Приводим клавиши к keys.txt (раскладка SDLPoP). Работа делится надвое, и
здесь только то, что не трогает игровую логику: переназначения (A) и три
мелкие функции поверх готовых механизмов (B). Читы, требующие правки
логики, и осмотр соседних комнат — фазы C и D, отложены.
ПЕРЕНАЗНАЧЕНИЯ (A)
U -> Shift+I переворот экрана; U отдан «комнате сверху»
Esc -> Backspace меню; Esc остаётся дублёром, как у SDLPoP
F7 / F8 -> - / + ±минута, основной ряд и цифровой блок
- / + -> Ctrl+- / Ctrl++ обход комнат (наш отладочный телепорт)
I -> Ctrl+I бессмертие
P -> Ctrl+P режим скорости
1 и 2 -> Ctrl+F стоп-кадр, теперь одной клавишей
F10 в игре -> Ctrl+Q вторая клавиша выхода; F10 ловится глобально
Плюс новое на готовых путях: Ctrl+A — рестарт уровня, Ctrl+V — версия
сборки (функция была, её показывал только старт), Ctrl+D — отладочная
строка (тот же тумблер, что в Settings; POP.CFG не пишем), Home / Page Up —
дублёры диагональных прыжков (у SDLPoP это не отдельное действие, а те же
Up+Left / Up+Right, поэтому просто добавляются к стрелкам).
Все наши сверхштатные клавиши ушли под Ctrl, чтобы не занимать голые буквы
из раскладки, и вписаны в keys.txt отдельным разделом. Ctrl+B намеренно
не занята: keys.txt держит её под «вернуться в комнату Кида» (фаза D).
ФУНКЦИИ (B)
Space «сколько осталось» (seg000:612). Не печатает сама: поднимает тот
же pop_show_time, которым пользуется автоматическое объявление
минут, и строку собирает time_msg() — «59 MINUTES LEFT» и «11
SECONDS LEFT» остаются в одном месте.
T постоянный показ таймера. Переиспользует поле DBG_F_TIME
отладочной строки, своего рендера нет. У верхней полосы теперь
три состояния, и отслеживается РЕЖИМ (0 нет / 1 таймер / 2 всё),
а не флаг: переход «таймер -> полоса» тоже перерисовывает всё.
Ctrl+R возврат в заставку — тот же переход, что «Restart Game» в меню.
ДВЕ ЛОВУШКИ, найденные по дороге
Модификатор обязан входить в САМО значение, а не в условие блока: с
`if (ctrl) { nav = ...; nav_prev = nav; }` при отпускании Ctrl кромка
застревала ненулевой и следующее нажатие глохло.
Один скан-код на два чита: Shift+I и Ctrl+I — это 0x43 в обоих случаях.
По той же причине ±минута требует ОТПУЩЕННОГО Ctrl (иначе сработает и
время, и обход комнат), а T — отпущенных Shift и Ctrl (Shift+T отдан
«добавить HP» в фазе C).
Обработчики положены в pop_frame_ui (банк 8), а не в резидент: там куча
всего 308 байт. Проверено в MAME: Ctrl+D поднимает строку
«Level 1, Room 1, Speed: NORMAL...», T — один таймер 59:30 без подписей,
Space — watchpoint на pop_show_time ловит запись значения 2 (именно
обработчик клавиши, автообъявление пишет 1).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -12,6 +12,7 @@
|
||||
| [`BUGS_OPEN.md`](BUGS_OPEN.md) | Открытые баги и незакрытые оптимизации |
|
||||
| [`impl_diff.md`](impl_diff.md) | **Осознанные расхождения с SDLPoP**: где сделано не дословно и почему. Новое расхождение — записью сюда, а не только комментарием в коде |
|
||||
| [`keys.txt`](keys.txt) | **Целевая раскладка управления**, к которой подгоняем SprPoP |
|
||||
| [`keys_plan.md`](keys_plan.md) | План перевода на неё: что совпадает, что переназначить, каких функций нет вовсе |
|
||||
|
||||
## Производительность
|
||||
|
||||
|
||||
@@ -33,8 +33,8 @@
|
||||
* Backspace: Display the in-game menu. (Esc will also display the menu by default, but you can turn that off.)
|
||||
|
||||
* Shift+L: Go to next level.
|
||||
* -: Decrease remaining time by one minute.
|
||||
* +: Increase remaining time by one minute.
|
||||
* -: Decrease remaining time by one minute. (Both the main row and the keypad.)
|
||||
* +: Increase remaining time by one minute. (Both the main row and the keypad.)
|
||||
* R: Resurrect kid.
|
||||
* K: Kill guard.
|
||||
* Shift+I: Flip the screen upside down.
|
||||
@@ -56,3 +56,23 @@
|
||||
* ]: Shift kid 1 pixel to the right.
|
||||
* T: Toggle display of timer (remaining minutes:seconds).
|
||||
|
||||
===
|
||||
|
||||
Sprinter-specific debug keys (not in the original; all under Ctrl so that no
|
||||
plain letter is taken away from the layout above):
|
||||
|
||||
* Ctrl+I: Immortality, cycling off -> combat only -> combat and minor damage.
|
||||
* Ctrl+P: Speed mode.
|
||||
* Ctrl+F: Freeze / unfreeze the frame (was 1 and 2).
|
||||
* Ctrl+D: Debug bar (level/room/... in the top border) on/off. Same switch
|
||||
as the Settings screen has; the shortcut does not write POP.CFG,
|
||||
saving stays with Settings.
|
||||
(The per-phase colour profiling of the border is a different thing
|
||||
and stays a build option: make PROF=1.)
|
||||
* Ctrl++ / Ctrl+-: Teleport to the next / previous room by number (ROOMNAV).
|
||||
The plain +/- belong to the timer, as in the original; the debug
|
||||
walk moved onto the same keys under Ctrl so muscle memory keeps.
|
||||
|
||||
Note: Ctrl+B is deliberately NOT used here — the layout above reserves it for
|
||||
"go back to the room where the prince is".
|
||||
|
||||
|
||||
@@ -0,0 +1,164 @@
|
||||
# План: перевод управления на раскладку `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 — делать ли их вообще: это читы и отладочный осмотр, к
|
||||
прохождению игры отношения не имеющие.
|
||||
Reference in New Issue
Block a user