Приводим клавиши к 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>
12 KiB
План: перевод управления на раскладку 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— воскрешение Кида: сложнее прочих, поднимает мёртвого персонажа и должен согласоваться с уже существующим гейтом «мёртв» (memorypop_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) — это её прямое применение, и
именно поэтому фаза идёт последней.
Фаза E — F12 скриншот. Помечен опциональным; предлагаю не делать
вовсе: файл на 80 КБ и запись на диск посреди кадра.
5. Открытые вопросы
- К1 — кому отдать
+/−: времени (какkeys.txt) или обходу комнат? - Что делать с нашими сверхштатными клавишами (
Iбессмертие,Pскорость,1/2стоп-кадр): оставить как есть, увести под отладочную сборку или выбросить? - Нужны ли
Home/Page Upкак дублёры диагональных прыжков — на IBM-клавиатуре Sprinter они есть, но комбинацияUp+Leftуже работает. - Фазы C и D — делать ли их вообще: это читы и отладочный осмотр, к прохождению игры отношения не имеющие.