libc: пока raw-клавиатура открыта, не звать обработчик DSS — он крал наши скан-коды
Корень двух багов SprPoP (KBD-STUCK-WAIT, частично GRAB-KBD-TIMING) нашёлся в исходниках DSS (docs/sources/Estex-DSS): обработчик прерывания DSS живёт в IM1 по 0x0038 и ПЕРВЫМ ДЕЛОМ делает `CALL KEYSCAN`, а тот вычерпывает FIFO SIO досуха. Наш трамплин проверял «есть ли клавиатурный байт» один раз, на входе в прерывание, а хвост кадрового пути уходил в DSS — значит скан-код, прилетевший позже, доставался DSS и уезжал в его буфер. Rx-overrun при этом НЕ взводится (байт не потерян железом, а прочитан не тем владельцем) — отсюда и загадка исходного диагноза: бит залип при `_kbdraw_overrun == 0`. Измерено в MAME (брейки + totalcycles): окно 738 тактов (~34 мкс) на каждом кадровом прерывании, из них 481 такт — пролог самого DSS. Поэтому проверка FIFO перед chain'ом снимает лишь треть и не годится (пробовали, кражи продолжались); кадровый путь при открытом raw теперь заканчивается приватным RETI, окно = 0. Цена: на это время у DSS замирает опрос мыши и мигание текстового курсора — зафиксировано в <kbd_raw.h>. Пойманный случай (старая сборка): DSS прочитал 0x74 (make стрелки «вправо») при _kbdraw_pending = EXT, то есть посылку E0 74 разорвало пополам между двумя владельцами канала. Проверка: брейк на входе KEYSCAN с условием «страница точно DSS + raw открыт» до правки срабатывал мгновенно (50/с), после — молчит; положительный контроль на нашем RETI срабатывает сразу. Трамплин 300 -> 310 Б (буфер W2-копии поднят 336 -> 384, запас 74 Б); размерный эталон обновлён: +10 Б у программ, линкующих IRQ. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -23,6 +23,16 @@
|
||||
* cbl_open()/cbl_close() (<cbl.h>) — тот же приватный IM2-хук, не
|
||||
* чейнящийся к DSS.
|
||||
*
|
||||
* КАДРОВОЕ ОБСЛУЖИВАНИЕ DSS НА ЭТО ВРЕМЯ ОСТАНОВЛЕНО. Пока raw открыт,
|
||||
* трамплин НЕ вызывает обработчик прерывания DSS вообще: тот первым делом
|
||||
* зовёт свой KEYSCAN, который вычерпывает FIFO SIO и уводит наши байты
|
||||
* (потерянный make = несработавшее нажатие, потерянный break = залипшая
|
||||
* клавиша; поймано в MAME 2026-08-28). Вместе с KEYSCAN замирают и
|
||||
* остальные его кадровые дела — опрос мыши (Dss.Mouse.GetPackets) и
|
||||
* мигание текстового курсора. ЗНАЧИТ: приложению, которому нужна мышь
|
||||
* через DSS, raw-канал открывать нельзя (мышь встанет); клавиатурные
|
||||
* события всё равно берутся из kbd_raw_down().
|
||||
*
|
||||
* КОДЫ КЛАВИШ: значения ниже — общеизвестный стандарт AT/PS-2 Scan
|
||||
* Code Set 2 (не специфика Sprinter). TODO до использования в PoC:
|
||||
* подтвердить в MAME, что реальный поток байт с SIO-A клавиатуры
|
||||
|
||||
+5
-4
@@ -30,10 +30,11 @@
|
||||
#define _IRQ_VEC_BUF_SIZE (256 + 257)
|
||||
|
||||
/* Буфер под W2-копию кадрового трамплина (small/huge — _irq_tramp в
|
||||
* W1). С запасом над реальным размером трамплина (267 Б после
|
||||
* упаковки held-карты клавиатуры в биты, 2026-07-30 — проверять
|
||||
* __irq_tramp_end при правках, запас держать >= 60 Б). */
|
||||
#define _IRQ_TRAMP_BUF_SIZE 336
|
||||
* W1). С запасом над реальным размером трамплина (310 Б после отказа
|
||||
* звать обработчик DSS, пока открыт raw-канал, 2026-08-28 — проверять
|
||||
* `grep 'A _CODE' libc/build/fast/irq/_irq_tramp.rel` при правках,
|
||||
* запас держать >= 60 Б). */
|
||||
#define _IRQ_TRAMP_BUF_SIZE 384
|
||||
|
||||
extern uint8_t _irq_vec_buf[_IRQ_VEC_BUF_SIZE];
|
||||
|
||||
|
||||
+36
-1
@@ -13,7 +13,9 @@
|
||||
* клавиши) в битовую карту `_kbdraw_down[]` (бит на код, 64 Б),
|
||||
* и к DSS НЕ идём
|
||||
* (private RETI — тот же паттерн, что и у CBL ниже). Пока raw
|
||||
* открыт, DSS клавиатуру не видит вообще (см. <kbd_raw.h>).
|
||||
* открыт, DSS клавиатуру не видит вообще (см. <kbd_raw.h>) — и на
|
||||
* кадровом пути тоже: пока raw открыт, обработчик DSS НЕ вызывается
|
||||
* совсем (иначе его KEYSCAN крадёт наши байты — см. tr_frame_exit).
|
||||
* - CBL (бит 7 порта 0xFE) — только при зарегистрированном хуке
|
||||
* _irq_cbl_hook (иначе бит подтянут к 1); личное прерывание, RETI
|
||||
* без чейна к DSS;
|
||||
@@ -312,6 +314,39 @@ void _irq_tramp(void) __naked
|
||||
ld a, (__irq_saved_w1) ; вернуть прерванную W1 перед chain
|
||||
out (#_IRQ_W1_PORT), a
|
||||
tr_frame_exit:
|
||||
;; --- ПОКА RAW ОТКРЫТ, В DSS НЕ ХОДИМ ВООБЩЕ ---
|
||||
;; Хвост кадрового пути уходил в DSS (0x0038), а его обработчик
|
||||
;; INTx38_Handler ПЕРВЫМ ДЕЛОМ зовёт KEYSCAN, и тот вычерпывает FIFO
|
||||
;; SIO досуха (docs/sources/Estex-DSS/DSS/DSS-MAIN.ASM,
|
||||
;; KEYINTER.ASM:KEYSCAN.RESCAN). Наша проверка «есть ли байт» стоит в
|
||||
;; НАЧАЛЕ трамплина, поэтому скан-код, прилетевший позже, доставался
|
||||
;; DSS и уезжал в ЕГО буфер — БЕЗ Rx-overrun. Украденный make =
|
||||
;; несработавшее нажатие, украденный break = залипшая навсегда
|
||||
;; клавиша при `_kbdraw_overrun == 0` (BUGS_OPEN KBD-STUCK-WAIT,
|
||||
;; GRAB-KBD-TIMING). Поймано в MAME 2026-08-28: DSS прочитал 0x74
|
||||
;; (make стрелки «вправо») при `_kbdraw_pending = EXT` — посылка
|
||||
;; `E0 74` разорвана пополам между двумя владельцами канала.
|
||||
;;
|
||||
;; Окно измерено брейками + totalcycles: от входа трамплина до
|
||||
;; чтения DSS — 738 тактов (~34 мкс), и открыто оно на КАЖДОМ
|
||||
;; кадровом прерывании (50/с). Из них 481 такт — пролог самого DSS
|
||||
;; (jp 0x38 → jp .Handler → call INTx38_Handler → 11 push → call
|
||||
;; KEYSCAN), то есть закрыть окно проверкой FIFO перед chain'ом
|
||||
;; нельзя: она снимает лишь треть (проверено там же).
|
||||
;;
|
||||
;; Поэтому пока raw открыт, кадровый путь заканчивается ПРИВАТНЫМ
|
||||
;; RETI и обработчик DSS не вызывается совсем — окно ровно ноль.
|
||||
;; ЦЕНА: на это время замирает кадровое обслуживание DSS —
|
||||
;; Dss.Mouse.GetPackets и мигание текстового курсора. Приложению с
|
||||
;; raw-клавиатурой (игре) не нужно ни то, ни другое; кому нужна мышь
|
||||
;; DSS одновременно с raw — не открывать raw (см. <kbd_raw.h>).
|
||||
ld a, (__kbdraw_active)
|
||||
or a, a
|
||||
jr Z, tr_chain_dss
|
||||
pop af
|
||||
ei
|
||||
reti
|
||||
tr_chain_dss:
|
||||
pop af
|
||||
.db 0xC3 ; jp 0x0038 (литерал — copy-safe)
|
||||
.dw 0x0038
|
||||
|
||||
Reference in New Issue
Block a user