1f16e8fa70
Клавиатура PS/2 обёртывает КАЖДЫЙ расширенный код парой E0 F0 12 / E0 12,
пока реально зажат Shift (замер на железе/MAME: правый шифт обёртывается
своим кодом 0x59). Это прямое и непрерывное свидетельство состояния
Shift — единственное доступное, потому что опросить PS/2 нельзя, а
typematic повторяет последнюю нажатую клавишу, то есть стрелку.
Оба декодера (_irq_tramp.c, kbd_raw_poll.c) читают обёртку в обе стороны:
обёртка есть -> Shift взвести; расширенный make без обёртки -> Shift
снять. Бит взводит общий писатель — достаточно обнулить префиксы, и код
уходит в plain-половину карты как make.
Это снимает размен, между крайностями которого мы метались:
- исключать модификаторы из сброса по overrun -> Shift залипал навсегда
(BUG-KBD-3);
- сбрасывать всю карту, как DSS -> Shift сносился каждым overrun'ом, а
при зажатом Shift тап стрелки это 10 байт в 3-байтовый FIFO, то есть
overrun почти гарантирован (BUG-KBD-4).
Теперь kbd_raw_sync снова не трогает модификаторы, и это безопасно:
залипание снимается первым же нажатием стрелки.
Раскладка трамплина: клавиатурный блок перевалил за 127 байт, а jp внутри
запрещён (копия в W2). Префиксные обработчики переехали вплотную к своим
cp, посередине тела стоят ретрансляторы tr_kbd_hub/tr_hub_notkbd/
tr_hub_dss. В kbd_raw_poll такого ограничения нет — там три jp.
Проверено в MAME: Shift переживает пять тапов подряд; штатное отпускание
снимает; искусственно залипший бит снимается первым тапом.
make size-check — роста нет.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
62 lines
4.1 KiB
C
62 lines
4.1 KiB
C
/*
|
|
* _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
|