/*
 * _kbdraw.h — внутренности raw-канала клавиатуры (НЕ публичный
 * заголовок; публичный интерфейс — <kbd_raw.h>).
 *
 * Всё состояние — плоские глобалы (живут в W2/_DATA во ВСЕХ memory-
 * режимах, см. sprinter_memory_modes) — трамплин прерывания
 * (libc/irq/_irq_tramp.c) обращается к ним БЕЗ W1-remap и без call,
 * поэтому раскладка памяти приложения тут ни при чём.
 */
#ifndef _KBDRAW_INTERNAL_H
#define _KBDRAW_INTERNAL_H

#include <stdint.h>

/* Биты _kbdraw_pending — накопленные префиксы PS/2 Scan Code Set 2,
 * ждущие завершающего байта кода (см. _irq_tramp.c). */
#define _KBDRAW_PEND_BREAK  0x01
#define _KBDRAW_PEND_EXT    0x02

extern uint8_t _kbdraw_active;      /* 0 = raw выключен (дефолт, трамплин
                                      * ведёт себя как раньше — прямо к DSS) */
extern uint8_t _kbdraw_pending;     /* FSM декодера make/break, см. выше */
extern uint8_t _kbdraw_overrun;     /* 1 = ISR поймал Rx-overrun SIO (потерян
                                      * байт → возможно потерян break); снимает
                                      * kbd_raw_sync (чистит _kbdraw_down) */
/* «Fake shift» (замер на железе/MAME 2026-08-03).  Пока реально зажат
 * Shift, клавиатура PS/2 обёртывает КАЖДЫЙ расширенный код парой служебных
 * посылок: перед make идёт E0 F0 12 (снять fake shift), после break — E0 12
 * (вернуть).  Это не клавиши, а прямое и непрерывное свидетельство того,
 * зажат ли Shift на самом деле, — и единственный способ узнать это, не
 * полагаясь на целость потока (PS/2 состояние опросить нельзя, а typematic
 * повторяет только ПОСЛЕДНЮЮ нажатую клавишу, то есть стрелку, не Shift).
 *
 * Декодеры (трамплин и kbd_raw_poll) используют его в обе стороны:
 *   - увидели fake shift  -> реальный Shift ЗАЖАТ  -> взвести plain-бит;
 *   - расширенный make БЕЗ предшествующей обёртки -> Shift ОТПУЩЕН ->
 *     снять plain-биты обоих Shift.
 * Отсюда: залипший Shift снимается первым же нажатием стрелки, а
 * kbd_raw_sync больше не обязан сбрасывать модификаторы «на всякий случай»
 * (из-за чего Shift отваливался посреди игры — BUG-KBD-4).
 *
 * Хранит промежуточное состояние: 1 = разобрана break-форма (E0 F0 12),
 * ждём расширенный код, который она обёртывает. */
extern uint8_t _kbdraw_fakesh;

/* Позиции бит модификаторов в карте (используют и декодеры на асме, и
 * kbd_raw_sync): L Shift 0x12 -> байт 2 бит 2, R Shift 0x59 -> байт 11 бит 1. */
#define _KBDRAW_LSH_BYTE  2
#define _KBDRAW_LSH_BIT   2
#define _KBDRAW_RSH_BYTE  11
#define _KBDRAW_RSH_BIT   1

/* Held-состояние: БИТ на скан-код, код>>3 = байт, код&7 = номер бита;
 * коды 0..255 обычные, 256..511 — расширенные (префикс 0xE0), т.е.
 * смещение +32 байта.  Упаковка вместо байта на код: 64 Б вместо 512 —
 * заметная доля _DATA на 32-килобайтной раскладке (замер PoP roomtest
 * 2026-07-30).  Ведёт трамплин прерывания (libc/irq/_irq_tramp.c),
 * читает kbd_raw_down(). */
extern uint8_t _kbdraw_down[64];

#endif
