3d586af031
- kbd_raw_sync: цикл вычерпывания SIO FIFO (не 1 байт/прерывание) — фикс залипания клавиш; overrun-wipe сбрасывает только пострадавшие клавиши, не модификаторы (typematic их не перечитывает). - Гайд docs/kbd-games.md; заметка о Rx-overrun в docs/TODO.md; справочник скан-кодов в docs/libc-reference.md. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
43 lines
2.5 KiB
C
43 lines
2.5 KiB
C
/*
|
|
* kbd_raw_sync.c — восстановление held-состояния после Rx-overrun SIO.
|
|
*
|
|
* Аппаратный приёмный FIFO SIO — 3 байта. Если прерывания запрещены
|
|
* достаточно долго (DI-окна графики/кадрового IRQ), а в этот момент
|
|
* приходит пачка скан-кодов (напр. быстрый тап стрелки = E0 74 + E0 F0 74,
|
|
* 5 байт) — FIFO переполняется, байт(ы) теряются аппаратно. Потерянный
|
|
* break → клавиша «залипает» в _kbdraw_down.
|
|
*
|
|
* Трамплин ловит overrun (RR1 бит5) и взводит _kbdraw_overrun. Приложение
|
|
* зовёт kbd_raw_sync() раз в кадр: при взведённом флаге сбрасывается
|
|
* held-состояние ВСЕХ клавиш, КРОМЕ модификаторов (Shift/Ctrl/Alt —
|
|
* таблица ниже). Обычные реально зажатые клавиши «перечитаются» их
|
|
* make-повтором (typematic) за ~0.1 с. Модификаторы НЕ сбрасываем
|
|
* принципиально: PS/2 автоповторяет только ПОСЛЕДНЮЮ нажатую клавишу,
|
|
* удерживаемый Shift при повторе стрелки не шлёт НИЧЕГО — сброшенный
|
|
* модификатор невозможно перечитать, он «отваливался» до перенажатия
|
|
* (баг PoP: Shift+→ = осторожный шаг превращался в бег, 2026-07-22).
|
|
* Цена: если overrun потерял именно break модификатора, тот залипнет до
|
|
* следующего нажатия — редкий случай против регулярного отвала.
|
|
*/
|
|
#include <string.h>
|
|
#include "_kbdraw.h"
|
|
|
|
/* Скан-коды модификаторов (PS/2 Set 2): L/R Shift, LCtrl, LAlt,
|
|
* RCtrl (E0 14 → +256), RAlt (E0 11 → +256). */
|
|
static const uint16_t _kbd_mod_codes[6] = {
|
|
0x12, 0x59, 0x14, 0x11, 0x0114, 0x0111
|
|
};
|
|
|
|
void kbd_raw_sync(void)
|
|
{
|
|
uint8_t save[6];
|
|
uint8_t i;
|
|
|
|
if (!_kbdraw_overrun) return;
|
|
_kbdraw_overrun = 0;
|
|
|
|
for (i = 0; i < 6; i++) save[i] = _kbdraw_down[_kbd_mod_codes[i]];
|
|
memset(_kbdraw_down, 0, sizeof(_kbdraw_down));
|
|
for (i = 0; i < 6; i++) _kbdraw_down[_kbd_mod_codes[i]] = save[i];
|
|
}
|