libc+libbgi: raw-клавиатура (held-state) + column-major блит спрайтов
libc/kbd: kbd_raw_open/close/down — сырой PS/2-канал клавиатуры с held-state (битовая карта _kbdraw_down[512], EXT-клавиши +256). Пока raw открыт, кадровый IRQ-трамплин перехватывает байт SIO у DSS и декодирует make/break (0xF0/0xE0-префиксы) сам. FIFO вычерпывается В ЦИКЛЕ (приёмный буфер SIO 3 байта; пачка break-кодов при одновременном отпускании иначе теряется → залипание клавиши). Буфер W2-трамплина поднят 224→288 Б под выросший обработчик. libc/conio: kbd_mod_state() — live-состояние модификаторов (ESTEX CTRLKEY $33h), Shift/Ctrl/Alt/Lock прямо сейчас, KBD_MOD_* маска. libbgi: gfx_blit_cols(x,y,img,flip) + _bgi_blit_cols_raw — блит column-major спрайта вертикальным accel-проходом, бесплатный горизонтальный флип (sstride<0), клип по экрану. Для персонажей. libbgi/atlas_load: восстанавливать W3 ДО записи a->count (atlas_t в --bank памяти резолвится через W3; count оставался мусором). tests/kbdraw — тест raw-клавиатуры; size-baseline +kbdraw. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+8
-2
@@ -30,8 +30,10 @@
|
||||
#define _IRQ_VEC_BUF_SIZE (256 + 257)
|
||||
|
||||
/* Буфер под W2-копию кадрового трамплина (small/huge — _irq_tramp в
|
||||
* W1). С запасом над реальным размером трамплина (~150 Б). */
|
||||
#define _IRQ_TRAMP_BUF_SIZE 224
|
||||
* W1). С запасом над реальным размером трамплина (225 Б после
|
||||
* FIFO-drain цикла в raw-клавиатурной ветке, 2026-07-16 — проверять
|
||||
* __irq_tramp_end при правках, запас держать ≥ 60 Б). */
|
||||
#define _IRQ_TRAMP_BUF_SIZE 288
|
||||
|
||||
extern uint8_t _irq_vec_buf[_IRQ_VEC_BUF_SIZE];
|
||||
|
||||
@@ -63,6 +65,10 @@ extern isr_t _irq_cbl_hook;
|
||||
#define _IRQ_CTC_CH2 0x12
|
||||
#define _IRQ_CTC_CH3 0x13
|
||||
#define _IRQ_SIO_A 0x19 /* SIO-A RR0: бит 0 = Rx available */
|
||||
#define _IRQ_SIO_DATA 0x18 /* SIO-A data — деструктивное чтение
|
||||
* (дренирует байт); читает либо DSS
|
||||
* (штатно), либо raw-канал клавиатуры
|
||||
* (libc/kbd/_kbdraw.h), но не оба сразу */
|
||||
|
||||
/* Захватить/отпустить IM2-таблицу (счётчик ссылок). ref: при первом
|
||||
* захвате строит таблицу, ставит I/IM2, взводит atexit-уборку;
|
||||
|
||||
+76
-3
@@ -3,8 +3,16 @@
|
||||
* версия с ЦЕПОЧКОЙ кадровых обработчиков и W1-remap для all-modes.
|
||||
*
|
||||
* Разбор источника (трогаем только AF, пока не выяснили):
|
||||
* - клавиатура (бит 0 порта 0x19 = SIO-A RR0) → сразу к DSS, БЕЗ
|
||||
* remap (W1 не трогаем — прерванный контекст сохранён как есть);
|
||||
* - клавиатура (бит 0 порта 0x19 = SIO-A RR0) → штатно сразу к DSS,
|
||||
* БЕЗ remap (W1 не трогаем — прерванный контекст сохранён как
|
||||
* есть). ИСКЛЮЧЕНИЕ: если raw-канал открыт (`_kbdraw_active`,
|
||||
* см. libc/kbd/_kbdraw.h, kbd_raw_open) — байт достаётся НАМ
|
||||
* (порт данных 0x18 читается один раз, деструктивно — либо мы,
|
||||
* либо DSS, не оба), декодируется make/break (PS/2 Scan Code
|
||||
* Set 2: 0xF0 — префикс отпускания, 0xE0 — префикс расширенной
|
||||
* клавиши) в битовую карту `_kbdraw_down[]`, и к DSS НЕ идём
|
||||
* (private RETI — тот же паттерн, что и у CBL ниже). Пока raw
|
||||
* открыт, DSS клавиатуру не видит вообще (см. <kbd_raw.h>).
|
||||
* - CBL (бит 7 порта 0xFE) — только при зарегистрированном хуке
|
||||
* _irq_cbl_hook (иначе бит подтянут к 1); личное прерывание, RETI
|
||||
* без чейна к DSS;
|
||||
@@ -29,6 +37,7 @@
|
||||
*/
|
||||
|
||||
#include "_irq.h"
|
||||
#include "../kbd/_kbdraw.h"
|
||||
|
||||
void _irq_tramp(void) __naked
|
||||
{
|
||||
@@ -38,7 +47,71 @@ void _irq_tramp(void) __naked
|
||||
rrca ; бит 0 — клавиатурный байт принят?
|
||||
jr NC, tr_notkbd
|
||||
|
||||
;; --- клавиатура: прямо к DSS, без remap ---
|
||||
;; --- клавиатура ---
|
||||
ld a, (__kbdraw_active)
|
||||
or a, a
|
||||
jr Z, tr_kbd_dss ; raw выключен — прежнее поведение
|
||||
|
||||
;; --- raw включён: байт наш целиком, DSS его не увидит ---
|
||||
;; ВЫЧЕРПЫВАЕМ FIFO SIO В ЦИКЛЕ (как эталон keybIntHandler /
|
||||
;; PS2_Scan в docs/samples): приёмный FIFO Z80 SIO 3 байта
|
||||
;; глубиной, а за один кадр при одновременном отпускании
|
||||
;; нескольких клавиш приходит ПАЧКА break-кодов (0xF0 code ...).
|
||||
;; Читать один байт за прерывание = переполнение FIFO = потеря
|
||||
;; break-кода = клавиша «залипает» навсегда (найдено 2026-07-16).
|
||||
push hl
|
||||
push de
|
||||
tr_kbd_drain:
|
||||
in a, (#_IRQ_SIO_DATA) ; читаем — тем самым дренируем байт
|
||||
cp #0xF0
|
||||
jr Z, tr_kbd_setbrk
|
||||
cp #0xE0
|
||||
jr Z, tr_kbd_setext
|
||||
|
||||
;; --- обычный байт кода: индекс в _kbdraw_down[код(+256 EXT)] ---
|
||||
ld hl, #__kbdraw_down
|
||||
ld d, #0
|
||||
ld e, a
|
||||
add hl, de
|
||||
ld a, (__kbdraw_pending)
|
||||
bit 1, a ; _KBDRAW_PEND_EXT?
|
||||
jr Z, tr_kbd_noext
|
||||
ld de, #256
|
||||
add hl, de
|
||||
tr_kbd_noext:
|
||||
ld a, (__kbdraw_pending)
|
||||
bit 0, a ; _KBDRAW_PEND_BREAK?
|
||||
jr Z, tr_kbd_mkdown
|
||||
xor a, a ; break → снять (0)
|
||||
jr tr_kbd_wr
|
||||
tr_kbd_mkdown:
|
||||
ld a, #1 ; make → взвести (1)
|
||||
tr_kbd_wr:
|
||||
ld (hl), a
|
||||
xor a, a
|
||||
ld (__kbdraw_pending), a ; сброс накопленных префиксов
|
||||
jr tr_kbd_next
|
||||
|
||||
tr_kbd_setbrk:
|
||||
ld hl, #__kbdraw_pending
|
||||
set 0, (hl)
|
||||
jr tr_kbd_next
|
||||
tr_kbd_setext:
|
||||
ld hl, #__kbdraw_pending
|
||||
set 1, (hl)
|
||||
;; fall through в tr_kbd_next
|
||||
tr_kbd_next:
|
||||
in a, (#_IRQ_SIO_A) ; ещё байт в FIFO?
|
||||
rrca ; бит 0 → CF
|
||||
jr C, tr_kbd_drain ; да — вычерпать следующий
|
||||
pop de
|
||||
pop hl
|
||||
pop af
|
||||
ei
|
||||
reti ; raw владеет каналом целиком — к DSS НЕ идём
|
||||
|
||||
tr_kbd_dss:
|
||||
;; --- прежнее поведение: прямо к DSS, без remap ---
|
||||
pop af
|
||||
.db 0xC3 ; jp nn
|
||||
__irq_dss_target::
|
||||
|
||||
Reference in New Issue
Block a user