030af74631
Симптом: 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>
61 lines
4.1 KiB
C
61 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». Часть 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
|