63a3b60524
Фича — плита-ПОТОЛОК (loose ряда 2 комнаты сверху, комн.5 (2,5) над комн.6): - check_press (seg006:1683) портирован целиком: кадры виса 87..99 и подъёма 135..140 «нажимают» тайл, за который Kid держится; кадр 79 — удар снизу (с проверкой action, как в оригинале); стояние — тайл под ним; - ряд −1 в pop_map.get_tile = ряд 2 комнаты сверху (порт find_room_of_tile), состояние тряски/падения — pop_ceil_modif[10]; do_knock(-1) трясёт потолок; - падение: mob переведён на координаты оригинала (y_loose_land/y_something), спавнится в ряду −1, по move_loose находит пол → loose_land: debris + do_knock; heal коридора — по прошлой позиции ДЛЯ КАЖДОЙ страницы; - урон: check_loose_fall_on_kid + fell_on_your_head (seq_52/seq_22, −1 HP) и «брызги» draw_hurt_splash (kid image 218); - колодец наверх: leave_room «вверх» проверяется ПЕРВЫМ (иначе y≈248 при подтягивании ловил check_leave_below и ронял Kid из уровня); - персистентность: общий tile-override (щебень внизу, пустота в комнате сверху) вместо debris-only. Окклюзия — приведена к оригиналу (найдено трассировкой собранного SDLPoP): - draw_tile_right/anim_right/draw_loose кладут спрайты в add_backtable НАПРЯМУЮ, минуя ptr_add_table → правая грань соседа («шахматка» столба 93), blueline и грани loose/пик соседа ВСЕГДА под персонажем. draw_other_overlay поверх Kid даёт только: 42 при левом соседе-поле, base, свои пики, bottom (overlay_mid_tile); - порядок объектов: тайл Kid (set_objtile_at_char) и порядок обхода (ряды 2→0, колонки 0→9), внутри тайла — сортировка по y (sort_curr_objs); то же правило для падающей плиты (pop_loose_mob_draw_over); - fore-слой рисуется ПОСЛЕ оверлеев (foretable после midtable), иначе тёмный скос floor_left_overlay ложился поверх колонны; - fore_tile больше не рисует bottom_id (в оригинале он в backtable) — минус 2..4 блита за кадр; - полоса потолка поверх Kid = draw_tile_bottom(1)+draw_loose(1)+draw_tile_fore (arg_0=1 добавляет в foretable), остальное — под ним; - следы оверлея восстанавливаются на ОБЕИХ страницах (pop_fore_heal). Прочее: - control(): при action bumped/in_freefall управление игнорируется целиком (seg005) — иначе прерванный присед терял dy(1)+dy(1) из medland и Kid навсегда оставался на 2px выше пола; - check_bumped: стена ищется по колонке переднего края (а не curr_col) + гард разворота — Kid больше не проходит сквозь опущенную решётку шва; - pop_floor_bake для смены floor→debris (bake_empty стирал верх стены ряда ниже — чёрный прямоугольник); - в pop_room_redraw_seam_left восстанавливается полоса потолка над решёткой. Проверено в MAME (bridge); эталон — собранный SDLPoP из applications/PoP/SDLPoP. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
433 lines
17 KiB
C
433 lines
17 KiB
C
/*
|
||
* pop_ctrl.c — управление Kid (Фаза K2b). Порт SDLPoP:
|
||
* вход — read_user_control/user_control/rest_ctrl_1/save_ctrl_1
|
||
* (seg006.c) поверх held-state <kbd_raw.h>;
|
||
* диспетчер — control() + control_standing/turning/startrun/running/
|
||
* crouched (seg005.c), Kid-only ветки (без меча/стражи);
|
||
* действия — forward/back/up/down_pressed, crouch, standing_jump,
|
||
* run_jump, safe_step (seg005.c).
|
||
*
|
||
* Map-запросы (стена/край/захват) ЗАСТАБЛЕНЫ «открытый пол» (map_* ниже) —
|
||
* реальная коллизия в K3/K4. Поэтому: forward -> всегда бег, down -> присед,
|
||
* back -> разворот, up+forward -> прыжок с места; osторожный шаг и climb
|
||
* помечены TODO(K3/K4).
|
||
*
|
||
* Значения CONTROL_* (types.h): RELEASED=0, IGNORE=1, HELD=-1;
|
||
* X: LEFT/FORWARD=-1, RIGHT/BACKWARD=+1; Y: UP=-1, DOWN=+1.
|
||
*/
|
||
#include <stdint.h>
|
||
#include <kbd_raw.h>
|
||
#include "pop_kid.h"
|
||
#include "pop_map.h"
|
||
|
||
/* Отладочные клавиши осторожного шага (эмуляция Shift+стрелка) для тестов в
|
||
* MAME, где Shift трудно подать: J = шаг влево, L = шаг вправо. PS/2 set2
|
||
* scancodes. TODO: убрать после отладки. */
|
||
#define KBD_DBG_STEPL 0x3B /* J */
|
||
#define KBD_DBG_STEPR 0x4B /* L */
|
||
|
||
/* ---- CONTROL_* и seq/frame id (подмножество types.h) --------------- */
|
||
#define CONTROL_RELEASED 0
|
||
#define CONTROL_IGNORE 1
|
||
#define CONTROL_HELD (-1)
|
||
#define CONTROL_HELD_LEFT (-1)
|
||
#define CONTROL_HELD_RIGHT 1
|
||
#define CONTROL_HELD_FORWARD (-1)
|
||
#define CONTROL_HELD_BACKWARD 1
|
||
#define CONTROL_HELD_UP (-1)
|
||
#define CONTROL_HELD_DOWN 1
|
||
|
||
#define DIR_RIGHT 0 /* dir_0_right */
|
||
|
||
#define SEQ_1_START_RUN 1
|
||
#define SEQ_2_STAND 2
|
||
#define SEQ_3_STANDING_JUMP 3
|
||
#define SEQ_4_RUN_JUMP 4
|
||
#define SEQ_5_TURN 5
|
||
#define SEQ_6_RUN_TURN 6
|
||
#define SEQ_13_STOP_RUN 13
|
||
#define SEQ_26_CROUCH_WHILE_RUNNING 26
|
||
#define SEQ_43_START_RUN_AFTER_TURN 43
|
||
#define SEQ_49_STAND_UP_FROM_CROUCH 49
|
||
#define SEQ_50_CROUCH 50
|
||
#define SEQ_79_CROUCH_HOP 79
|
||
#define SEQ_STEP_BASE 28 /* +distance(1..14) = seq 29..42 шаг-N */
|
||
#define SEQ_39_UNSAFE_STEP 39 /* шаг за кромку (distance 11) */
|
||
#define SEQ_44_STEP_ON_EDGE 44
|
||
#define SEQ_14_JUMP_INTO_CEILING 14 /* прыжок вверх: сверху стена/пол */
|
||
#define SEQ_28_JUMP_NOTHING_ABOVE 28 /* прыжок вверх: сверху пусто */
|
||
#define SEQ_25_HANG_AGAINST_WALL 25 /* вис у стены (Shift в висе) */
|
||
|
||
#define FRAME_7_RUN 7
|
||
#define FRAME_11_RUN 11
|
||
#define FRAME_15_STAND 15
|
||
#define FRAME_48_TURN 48
|
||
#define FRAME_50_TURN 50
|
||
#define FRAME_67_JUMPUP1 67
|
||
#define FRAME_70_JUMPHANG 70
|
||
#define FRAME_87_HANG1 87
|
||
#define FRAME_109_CROUCH 109
|
||
|
||
/* ---- Состояние управления (seg006 globals) ------------------------ *
|
||
* control_x/y/shift — «сырое» состояние осей ЭТОГО кадра (абсолютно:
|
||
* X LEFT/-1..RIGHT/+1); *_forward/backward/up/down/shift2 — конечный
|
||
* автомат held/released/ignore (авто-повтор); ctrl1_* — их память между
|
||
* кадрами (rest/save). */
|
||
static int8_t control_x, control_y, control_shift;
|
||
static int8_t control_forward, control_backward, control_up, control_down, control_shift2;
|
||
static int8_t ctrl1_forward, ctrl1_backward, ctrl1_up, ctrl1_down, ctrl1_shift2;
|
||
|
||
/* ---- seqtbl_offset_char: сменить последовательность Kid ------------ *
|
||
* Обёртка над kid_set_seq (единая точка в pop_kid — kid_seq_off/kid_seqtbl
|
||
* не дублируются в этот TU). */
|
||
#define seqtbl_offset_char(seq) kid_set_seq(seq)
|
||
|
||
static int8_t release_arrows(void)
|
||
{
|
||
control_backward = control_forward = control_up = control_down = CONTROL_RELEASED;
|
||
return CONTROL_IGNORE; /* seg006: return 1 */
|
||
}
|
||
|
||
/* Край/стена впереди — из pop_map (get_edge_distance): pop_edge_distance()
|
||
* возвращает дистанцию и ставит pop_edge_type() = EDGE_WALL/FLOOR/CLOSER. */
|
||
|
||
/* ---- Действия (seg005) -------------------------------------------- */
|
||
static void crouch(void)
|
||
{
|
||
seqtbl_offset_char(SEQ_50_CROUCH);
|
||
control_down = release_arrows();
|
||
}
|
||
|
||
static void standing_jump(void)
|
||
{
|
||
control_up = control_forward = CONTROL_IGNORE;
|
||
seqtbl_offset_char(SEQ_3_STANDING_JUMP);
|
||
}
|
||
|
||
static void run_jump(void)
|
||
{
|
||
/* Оригинал выравнивает Kid по краю пола (нужны tile-запросы) — это
|
||
* полировка K3; K2b просто запускает run-jump. */
|
||
if (Kid.frame >= FRAME_7_RUN) {
|
||
control_up = release_arrows();
|
||
seqtbl_offset_char(SEQ_4_RUN_JUMP);
|
||
}
|
||
}
|
||
|
||
static void safe_step(void); /* fwd */
|
||
|
||
static void forward_pressed(void)
|
||
{
|
||
int distance = pop_edge_distance();
|
||
if (pop_edge_type() == EDGE_WALL && distance < 8) {
|
||
/* рядом стена — вместо бега осторожный шаг (в стену не разбежится) */
|
||
if (control_forward == CONTROL_HELD)
|
||
safe_step();
|
||
} else {
|
||
seqtbl_offset_char(SEQ_1_START_RUN);
|
||
}
|
||
}
|
||
|
||
static void back_pressed(void)
|
||
{
|
||
control_backward = release_arrows();
|
||
/* Kid без меча -> просто разворот. */
|
||
seqtbl_offset_char(SEQ_5_TURN);
|
||
}
|
||
|
||
static void down_pressed(void)
|
||
{
|
||
control_down = CONTROL_IGNORE; /* без авто-повтора */
|
||
/* У края пола (край сзади) со зацепом снизу — спуск на этаж (seq_68);
|
||
* у передней кромки — отступ; иначе присед. Решает pop_down_action. */
|
||
if (!pop_down_action())
|
||
crouch();
|
||
}
|
||
|
||
/* Прыжок вверх в стойке (seg005 check_jump_up): чистый вертикальный прыжок
|
||
* ЛИБО прыжок-с-зацепом за уступ выше (запрыгнуть на этаж вверх). Выбор seq
|
||
* + выравнивание Kid.x — в pop_jump_up_seq (pop_map). */
|
||
static void jump_up(void)
|
||
{
|
||
control_up = release_arrows();
|
||
seqtbl_offset_char(pop_jump_up_seq());
|
||
}
|
||
|
||
static void up_pressed(void)
|
||
{
|
||
/* (дверь уровня/телепорт — нет в тесте.) ↑+forward = прыжок с места;
|
||
* иначе вертикальный прыжок вверх. */
|
||
if (control_x == CONTROL_HELD_FORWARD)
|
||
standing_jump();
|
||
else
|
||
jump_up();
|
||
}
|
||
|
||
/* Осторожный шаг (Shift+forward): шаг РОВНО до кромки/стены. distance>0 —
|
||
* шаг длины distance (seq 29..42 = step1..step14); ==0 у края — шаг на
|
||
* кромку (seq_44) либо неосторожный шаг за край (seq_39). Порт seg005. */
|
||
static void safe_step(void)
|
||
{
|
||
int distance;
|
||
control_shift2 = CONTROL_IGNORE; /* без авто-повтора */
|
||
control_forward = CONTROL_IGNORE;
|
||
distance = pop_edge_distance();
|
||
if (distance) {
|
||
Kid.repeat = 1;
|
||
seqtbl_offset_char((uint8_t)(distance + SEQ_STEP_BASE));
|
||
} else if (pop_edge_type() == EDGE_WALL) {
|
||
/* вплотную к стене: маленький шаг-1 — check_bumped отскочит назад
|
||
* (шаг назад со звуком, как оригинал), НЕ seq_39 (шаг за край=падение). */
|
||
Kid.repeat = 1;
|
||
seqtbl_offset_char((uint8_t)(1 + SEQ_STEP_BASE));
|
||
} else if (Kid.repeat != 0) {
|
||
Kid.repeat = 0;
|
||
seqtbl_offset_char(SEQ_44_STEP_ON_EDGE);
|
||
} else {
|
||
seqtbl_offset_char(SEQ_39_UNSAFE_STEP); /* реальный обрыв (edge=CLOSER) */
|
||
}
|
||
}
|
||
|
||
/* ---- control_* обработчики состояний ------------------------------ */
|
||
static void control_crouched(void)
|
||
{
|
||
if (control_y != CONTROL_HELD_DOWN) {
|
||
seqtbl_offset_char(SEQ_49_STAND_UP_FROM_CROUCH);
|
||
} else if (control_forward == CONTROL_HELD) {
|
||
control_forward = CONTROL_IGNORE;
|
||
seqtbl_offset_char(SEQ_79_CROUCH_HOP);
|
||
}
|
||
}
|
||
|
||
static void control_standing(void)
|
||
{
|
||
/* Kid charid_0, без меча: остаётся нижняя часть control_standing. */
|
||
if (control_shift == CONTROL_HELD) {
|
||
if (control_backward == CONTROL_HELD) back_pressed();
|
||
else if (control_up == CONTROL_HELD) up_pressed();
|
||
else if (control_down == CONTROL_HELD) down_pressed();
|
||
else if (control_x == CONTROL_HELD_FORWARD && control_forward == CONTROL_HELD)
|
||
safe_step();
|
||
} else if (control_forward == CONTROL_HELD) {
|
||
if (control_up == CONTROL_HELD) standing_jump(); /* keyboard mode */
|
||
else forward_pressed();
|
||
} else if (control_backward == CONTROL_HELD) {
|
||
back_pressed();
|
||
} else if (control_up == CONTROL_HELD) {
|
||
if (control_forward == CONTROL_HELD) standing_jump();
|
||
else up_pressed();
|
||
} else if (control_down == CONTROL_HELD) {
|
||
down_pressed();
|
||
} else if (control_x == CONTROL_HELD_FORWARD) {
|
||
forward_pressed();
|
||
}
|
||
}
|
||
|
||
static void control_turning(void)
|
||
{
|
||
if (control_shift >= CONTROL_RELEASED &&
|
||
control_x == CONTROL_HELD_FORWARD && control_y >= CONTROL_RELEASED) {
|
||
seqtbl_offset_char(SEQ_43_START_RUN_AFTER_TURN);
|
||
}
|
||
}
|
||
|
||
static void control_startrun(void)
|
||
{
|
||
if (control_y == CONTROL_HELD_UP && control_x == CONTROL_HELD_FORWARD)
|
||
standing_jump();
|
||
}
|
||
|
||
static void control_running(void)
|
||
{
|
||
/* Стену НЕ обрабатываем тут — check_bumped (pop_phys_tick) даёт отскок
|
||
* seq_47 при беге в стену (как оригинал), с корректной позицией. */
|
||
if (control_x == CONTROL_RELEASED &&
|
||
(Kid.frame == FRAME_7_RUN || Kid.frame == FRAME_11_RUN)) {
|
||
control_forward = release_arrows();
|
||
seqtbl_offset_char(SEQ_13_STOP_RUN);
|
||
} else if (control_x == CONTROL_HELD_BACKWARD) {
|
||
control_backward = release_arrows();
|
||
seqtbl_offset_char(SEQ_6_RUN_TURN);
|
||
} else if (control_y == CONTROL_HELD_UP && control_up == CONTROL_HELD) {
|
||
run_jump();
|
||
} else if (control_down == CONTROL_HELD) {
|
||
control_down = CONTROL_IGNORE;
|
||
seqtbl_offset_char(SEQ_26_CROUCH_WHILE_RUNNING);
|
||
}
|
||
}
|
||
|
||
/* ---- Вис (seg005 control_hanging/can_climb_up/hang_fall) ---------- *
|
||
* Тайловые решения (можно ли подтянуться, куда сорваться) — в pop_map;
|
||
* здесь управление осями control_*. */
|
||
static void hang_fall(void)
|
||
{
|
||
control_down = release_arrows();
|
||
seqtbl_offset_char(pop_hang_fall_seq()); /* seq_23/seq_11 (+ выравнивание x) */
|
||
}
|
||
|
||
static void can_climb_up(void)
|
||
{
|
||
control_up = control_shift2 = release_arrows();
|
||
seqtbl_offset_char(pop_hang_climb_up_seq()); /* seq_10 / seq_73 */
|
||
}
|
||
|
||
static void control_hanging(void)
|
||
{
|
||
if (control_y == CONTROL_HELD && pop_hang_grab_ready()) {
|
||
can_climb_up(); /* ↑ — подтянуться */
|
||
} else if (control_shift == CONTROL_HELD) {
|
||
int8_t w = pop_hang_wall();
|
||
if (w > 0) seqtbl_offset_char(SEQ_25_HANG_AGAINST_WALL); /* у стены */
|
||
else if (w < 0) hang_fall(); /* сорваться */
|
||
/* w==0: сверху пол — держимся (ничего) */
|
||
} else {
|
||
hang_fall(); /* отпустил Shift — сорваться */
|
||
}
|
||
}
|
||
|
||
/* control_jumpup (seg005): в старте прыжка вверх ←/→ или forward → перевести
|
||
* в прыжок с места. */
|
||
static void control_jumpup(void)
|
||
{
|
||
if (control_x == CONTROL_HELD_FORWARD || control_forward == CONTROL_HELD)
|
||
standing_jump();
|
||
}
|
||
|
||
/* control() — диспетчер по кадру (seg005.c:252), Kid жив, без меча. */
|
||
static void control(void)
|
||
{
|
||
uint8_t f = Kid.frame;
|
||
/* seg005 control(): в отскоке (bumped) и в свободном падении управление
|
||
* НЕ обрабатывается вовсе — только гасятся стрелки. Без этого игрок
|
||
* прерывает присед после удара (medland/плита по голове) нажатием ↑, и
|
||
* последовательность не доигрывает свои dy(1)+dy(1), компенсирующие
|
||
* стартовый dy(-2) → Kid навсегда остаётся на 2px выше пола (баг «Y на
|
||
* пару пикселей меньше, чем должен»). */
|
||
if (Kid.action == 5 || Kid.action == 4) { /* bumped / in_freefall */
|
||
release_arrows();
|
||
return;
|
||
}
|
||
if (f == FRAME_15_STAND || (f >= FRAME_50_TURN && f < 53))
|
||
control_standing();
|
||
else if (f == FRAME_48_TURN)
|
||
control_turning();
|
||
else if (f < 4)
|
||
control_startrun();
|
||
else if (f >= FRAME_67_JUMPUP1 && f < FRAME_70_JUMPHANG)
|
||
control_jumpup();
|
||
else if (f < FRAME_15_STAND)
|
||
control_running();
|
||
else if (f >= FRAME_87_HANG1 && f < 100)
|
||
control_hanging();
|
||
else if (f == FRAME_109_CROUCH)
|
||
control_crouched();
|
||
}
|
||
|
||
/* ---- Модель ввода (seg006) ---------------------------------------- */
|
||
static void read_input(void)
|
||
{
|
||
uint8_t l = kbd_raw_down(KBD_LEFT);
|
||
uint8_t r = kbd_raw_down(KBD_RIGHT);
|
||
uint8_t u = kbd_raw_down(KBD_UP);
|
||
uint8_t d = kbd_raw_down(KBD_DOWN);
|
||
/* Отладочный осторожный шаг: J/L = Shift+влево/вправо (см. KBD_DBG_STEP*). */
|
||
uint8_t sl = kbd_raw_down(KBD_DBG_STEPL);
|
||
uint8_t sr = kbd_raw_down(KBD_DBG_STEPR);
|
||
if (sl) l = 1;
|
||
if (sr) r = 1;
|
||
control_x = r ? CONTROL_HELD_RIGHT : (l ? CONTROL_HELD_LEFT : CONTROL_RELEASED);
|
||
control_y = d ? CONTROL_HELD_DOWN : (u ? CONTROL_HELD_UP : CONTROL_RELEASED);
|
||
control_shift = (sl || sr || kbd_raw_down(KBD_LSHIFT) || kbd_raw_down(KBD_RSHIFT))
|
||
? CONTROL_HELD : CONTROL_RELEASED;
|
||
}
|
||
|
||
/* read_user_control (seg006:1557): «свежее нажатие» (RELEASED->HELD) с
|
||
* подавлением авто-повтора (IGNORE держится, пока клавишу не отпустят). */
|
||
static void read_user_control(void)
|
||
{
|
||
if (control_forward >= CONTROL_RELEASED) {
|
||
if (control_x == CONTROL_HELD_FORWARD) {
|
||
if (control_forward == CONTROL_RELEASED) control_forward = CONTROL_HELD;
|
||
} else control_forward = CONTROL_RELEASED;
|
||
}
|
||
if (control_backward >= CONTROL_RELEASED) {
|
||
if (control_x == CONTROL_HELD_BACKWARD) {
|
||
if (control_backward == CONTROL_RELEASED) control_backward = CONTROL_HELD;
|
||
} else control_backward = CONTROL_RELEASED;
|
||
}
|
||
if (control_up >= CONTROL_RELEASED) {
|
||
if (control_y == CONTROL_HELD_UP) {
|
||
if (control_up == CONTROL_RELEASED) control_up = CONTROL_HELD;
|
||
} else control_up = CONTROL_RELEASED;
|
||
}
|
||
if (control_down >= CONTROL_RELEASED) {
|
||
if (control_y == CONTROL_HELD_DOWN) {
|
||
if (control_down == CONTROL_RELEASED) control_down = CONTROL_HELD;
|
||
} else control_down = CONTROL_RELEASED;
|
||
}
|
||
if (control_shift2 >= CONTROL_RELEASED) {
|
||
if (control_shift == CONTROL_HELD) {
|
||
if (control_shift2 == CONTROL_RELEASED) control_shift2 = CONTROL_HELD;
|
||
} else control_shift2 = CONTROL_RELEASED;
|
||
}
|
||
}
|
||
|
||
static void flip_control_x(void)
|
||
{
|
||
int8_t t;
|
||
control_x = (int8_t)-control_x;
|
||
t = control_forward; control_forward = control_backward; control_backward = t;
|
||
}
|
||
|
||
/* user_control (seg006:0DC0): «вперёд» относительно направления Kid. */
|
||
static void user_control(void)
|
||
{
|
||
if (Kid.direction >= DIR_RIGHT) {
|
||
flip_control_x();
|
||
control();
|
||
flip_control_x();
|
||
} else {
|
||
control();
|
||
}
|
||
}
|
||
|
||
static void rest_ctrl_1(void)
|
||
{
|
||
control_forward = ctrl1_forward; control_backward = ctrl1_backward;
|
||
control_up = ctrl1_up; control_down = ctrl1_down; control_shift2 = ctrl1_shift2;
|
||
}
|
||
static void save_ctrl_1(void)
|
||
{
|
||
ctrl1_forward = control_forward; ctrl1_backward = control_backward;
|
||
ctrl1_up = control_up; ctrl1_down = control_down; ctrl1_shift2 = control_shift2;
|
||
}
|
||
|
||
/* ---- Публичный API ------------------------------------------------ */
|
||
int pop_ctrl_init(void)
|
||
{
|
||
control_forward = control_backward = control_up = control_down = CONTROL_RELEASED;
|
||
control_shift2 = CONTROL_RELEASED;
|
||
ctrl1_forward = ctrl1_backward = ctrl1_up = ctrl1_down = ctrl1_shift2 = CONTROL_RELEASED;
|
||
return kbd_raw_open();
|
||
}
|
||
|
||
void pop_ctrl_close(void)
|
||
{
|
||
kbd_raw_close();
|
||
}
|
||
|
||
int8_t pop_ctrl_shift_held(void)
|
||
{
|
||
return (int8_t)(control_shift == CONTROL_HELD);
|
||
}
|
||
|
||
void pop_ctrl_tick(void)
|
||
{
|
||
kbd_raw_sync(); /* снять залипшее после Rx-overrun SIO */
|
||
rest_ctrl_1();
|
||
read_input();
|
||
read_user_control();
|
||
user_control(); /* -> control(): может сменить Kid.curr_seq */
|
||
save_ctrl_1();
|
||
}
|