Files
Sprinter-SDCC/libc/kbd/_kbdraw.h
T
Александр Петров 030af74631 BUG-KBD-5: зажатый Shift снимался автоповтором стрелки
Симптом: Shift работал в одиночку и НЕ работал вместе со стрелками —
прыжок с зацепом не выходил (BUG-GRAB-1), а осторожный шаг срывался в бег.

Декодеры делали из «fake shift» два вывода, и второй был неверен:
  обёртка E0 F0 12 / E0 12 есть  -> Shift зажат -> взвести бит   — верно;
  расширенный make БЕЗ обёртки   -> Shift отпущен -> снять бит   — НЕТ.

Замер потока байт (MAME, breakpoint на выходе из in a,($18)): клавиатура
pc_kbd ms_naturl обёртку не шлёт вовсе — при зажатом Shift поток на ↑ ровно
`E0 75 E0 75 …`, ни одного F0/12.  А typematic-повторы идут непрерывно,
пока стрелка зажата, значит каждый повтор снимал реально зажатый Shift.
Короткий тап это маскировал: после отпускания стрелки Shift снова
становился последней клавишей, и его собственный автоповтор `12` взводил
бит обратно за ~30 мс.

Фикс: обратный вывод убран, расширенная клавиша о Shift не судит.
Состояние Shift ведут его собственные make/break 12 / F0 12 — они приходят
всегда.  Прямой вывод оставлен (дёшев и верен там, где обёртка есть).
Ушла ставшая ненужной _kbdraw_fakesh; трамплин короче на 36 Б (0x150→0x12C),
что важно — его клавиатурный блок упирается в диапазон jr.

Плата: потерянный при overrun break Shift снять нечем, модификатор может
залипнуть до перенажатия (BUG-KBD-3).  Размен решён как и раньше в
kbd_raw_sync: лучше залипание, чем отвал — сорванный посреди игры Shift
в PoP стоит жизни.

Проверено в MAME чтением _kbdraw_down: Shift+↑+→ зажаты 5 с (автоповтор
идёт) -> LSh остаётся 04; отпускание Shift -> 00.  Зацеп в игре
подтверждён пользователем.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-05 12:33:15 +03:00

61 lines
4.1 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* _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». Часть PS/2-клавиатур, пока реально зажат Shift, обёртывает
* расширенный код парой служебных посылок: перед make идёт E0 F0 12 (снять
* fake shift), после break — E0 12 (вернуть). Это не клавиши, а прямое
* свидетельство того, что Shift зажат, поэтому декодеры (трамплин и
* kbd_raw_poll) взводят по обёртке plain-бит Shift.
*
* ОБРАТНЫЙ ВЫВОД ЗАПРЕЩЁН (замер 2026-08-05, BUG-GRAB-1). Раньше отсюда
* делался и второй вывод: «расширенный make БЕЗ обёртки => Shift отпущен,
* снять plain-биты». Он неверен: обёртку шлют не все клавиатуры (в MAME
* Sprinter — pc_kbd ms_naturl — при зажатом Shift поток на стрелку вверх
* ровно `E0 75 E0 75 …`, ни одного F0/12), и она заведомо не сопровождает
* typematic-повторы. Результат: КАЖДЫЙ повтор зажатой стрелки снимал
* реально зажатый Shift, и Shift был неработоспособен вместе со стрелками.
*
* Состояние Shift ведётся его собственными make/break (12 / F0 12) — они
* приходят всегда; обёртка лишь подтверждает. Ценой этого потерянный при
* overrun'е break Shift снять нечем — лечится перенажатием Shift
* (см. kbd_raw_sync и BUG-KBD-3/4). */
/* Позиции бит модификаторов в карте (используют и декодеры на асме, и
* 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