Files
Sprinter-SDCC/applications/PoP/roomtest/pop_ctrl.h
T
snark13 cf06896dbd PoP roomtest: окно Char вокруг control() + общая шина ввода — база под ИИ стража
Инфраструктура пункта 2.  В оригинале у соперника НЕТ своего диспетчера:
autocontrol_* (seg002) выставляет те же глобалы control_*, что и ввод
игрока, а дальше исполняется тот же control() (seg005:252).  Значит перед
портом ИИ надо было привести к этому обе половины:

- control_forward/backward/up/down/shift2 перестали быть static в
  pop_ctrl.c — это общая шина синтетического ввода, объявлена в pop_ctrl.h
  вместе с POP_CONTROL_*;
- control() переименован в pop_control() и работает с Char, а не с Kid;
- ввод игрока обёрнут в окно Char (loadkid/user_control/savekid), как в
  play_frame оригинала.

Ловушка по дороге (ввод отвалился целиком, Kid не двигался): макрос
seqtbl_offset_char вёл на kid_set_seq, который пишет прямо в Kid, а
следом savekid затирал Kid копией Char со старой curr_seq.  В оригинале
seqtbl_offset_char работает именно с Char — макрос переведён на
pop_char_set_seq.  kid_set_seq остался для вызовов ВНЕ окна (pop_map).

Добавлен pop_savekid_state (Kid = Char без кадра): control() кадр не
трогает, а cur_frame в этот момент принадлежит тому, кто последним крутил
play_seq.

Проверено в MAME: бег и упор в стену работают как прежде.
Бюджет (комната 3, 125 кадров): 382 584..383 064 против 380 292..381 282,
то есть +2 300 тактов на копии окна.  0.891 кадра, запас 46 936.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-30 10:32:15 +03:00

51 lines
2.9 KiB
C

/*
* pop_ctrl.h — управление Kid (Фаза K2b): порт диспетчера control()
* (SDLPoP seg005.c) + модель ввода read_user_control/user_control
* (seg006.c) поверх held-state клавиатуры <kbd_raw.h>.
*
* Kid-only подмножество: без меча и стражи. Map-запросы (стена/край/
* захват) ЗАСТАБЛЕНЫ «открытый пол» — реальная коллизия (стоп у стены,
* падение в ямы, повисание) приходит в K3/K4. Даёт отклик на клавиши:
* бег влево/вправо, разворот, стоп, присед, прыжок с места, прыжок в
* беге, присед-прыжок.
*
* Раскладка (kbd_raw, PS/2 Set 2): ←/→ = движение, ↓ = присед, ↑ =
* прыжок вверх (с →), Shift = осторожный шаг (K3). ESC — выход (проверяет
* приложение сам, канал raw забирает весь ввод у DSS).
*/
#ifndef POP_CTRL_H
#define POP_CTRL_H
#include <stdint.h>
/* Открыть raw-канал клавиатуры и обнулить память авто-повтора.
* 0 — OK, -1 — ошибка (EBUSY и пр., см. kbd_raw_open). */
int pop_ctrl_init(void);
void pop_ctrl_close(void);
/* Один кадр ввода: прочитать клавиши -> обновить control_* -> прогнать
* диспетчер control() (может сменить Kid.curr_seq). Звать ПЕРЕД
* kid_tick() (play_seq продолжит с новой последовательности). */
void pop_ctrl_tick(void);
/* control_shift зажат ПРЯМО СЕЙЧАС? — для check_grab в физике (pop_map):
* зацеп за уступ в падении по Shift. Валидно после pop_ctrl_tick. */
int8_t pop_ctrl_shift_held(void);
/* ---- Шина синтетического ввода (порт глобалов control_* из seg005) ----
* В оригинале ИИ соперника (autocontrol_*, seg002) не имеет своего
* диспетчера: он ВЫСТАВЛЯЕТ эти переменные, а дальше исполняется тот же
* control(), что и для игрока. Значения — CONTROL_RELEASED/IGNORE/HELD. */
#define POP_CONTROL_RELEASED 0
#define POP_CONTROL_IGNORE 1
#define POP_CONTROL_HELD (-1)
extern int8_t control_forward, control_backward, control_up, control_down,
control_shift2;
/* Диспетчер (seg005:252) для АКТИВНОГО персонажа Char. Игрок идёт через
* pop_ctrl_tick (тот делает user_control с зеркалом «вперёд»), страж — из
* своего тика напрямую. */
void pop_control(void);
#endif