KBD: состояние Shift по «fake shift» — ни залипания, ни отвала
Клавиатура 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>
This commit is contained in:
@@ -23,6 +23,33 @@ 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 —
|
||||
|
||||
Reference in New Issue
Block a user