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:
2026-07-17 17:48:32 +03:00
parent e14b6745f7
commit 484b18d10c
19 changed files with 602 additions and 7 deletions
+84
View File
@@ -0,0 +1,84 @@
/*
* _bgi_blit_cols_raw — accel block-copy КОЛОНКАМИ (буфер column-major ->
* экран). Парный к _bgi_blit_rows_raw, но вертикальный проход: каждая
* КОЛОНКА копируется одним accel-burst'ом вниз (Port_Y авто-шагает),
* опкод LD A,A (0x7F — «копирование блока для вертикального прохода»,
* см. docs/reference/accel_r.txt). dst двигается на +1 (следующий x) на
* колонку; Port_Y сбрасывается в y0 перед каждой колонкой (accel шагает
* его внутри burst'а); src двигается на sstride на колонку.
*
* ЗАЧЕМ: бесплатный ГОРИЗОНТАЛЬНЫЙ флип персонажей — вызывающий подаёт
* src с конца (src+(w-1)*h) и sstride=-h, тогда правая колонка источника
* ложится в левый x экрана (зеркало). Реверс без CPU и без удвоения
* памяти. Спрайты персонажей хранятся column-major.
*
* ВХОД (__sdcccall(1)): src→HL, dst→DE; стек: w 4(ix), h 5(ix),
* sstride 6/7(ix), y0 8(ix). w — число КОЛОНОК (1..256, 0=256); h —
* высота колонки = размер accel-блока (1..256, 0=256); sstride — шаг
* адреса src между колонками (±); y0 — стартовый Port_Y. Callee-pop 5 Б.
*
* Raw: без клиппинга (вызывающий); W3 замаплен (_bgi_begin/end снаружи);
* банк выставлен вызывающим (0x5C прозрачный / 0x50 обычный). src ВНЕ W3.
* ОДИН DI на весь блит. Колонки > 256 строк режет вызывающий (h ≤ 256).
* Клоббер: AF/BC/DE/HL; IX сохраняется.
*/
#include "../_bgi.h"
void _bgi_blit_cols_raw(const uint8_t *src, uint8_t *dst,
uint8_t w, uint8_t h,
int sstride, uint8_t y0) __naked
{
(void)src; (void)dst; (void)w; (void)h; (void)sstride; (void)y0;
__asm
push ix
ld ix, #0
add ix, sp
;; SMC: размер accel-блока <- h (высота колонки)
ld a, 5 (ix)
ld (bc_len_imm), a
;; SMC: src-страйд между колонками (8-бит adc-цепочка, ± на вызов)
ld a, 6 (ix)
ld (bc_slo_imm), a
ld a, 7 (ix)
ld (bc_shi_imm), a
ld b, 4 (ix) ; B = число колонок (0 => 256: djnz)
ld c, 8 (ix) ; C = y0 (Port_Y, константа)
di ; один DI на весь блит
ld d, d ; 0x52 режим размера блока
ld a, #0
bc_len_imm = . - 1
ld b, b ; 0x40 стоп (B=счётчик не тронут)
bc_col:
ld a, c
out (#0x89), a ; Port_Y = y0 (сброс на верх колонки)
;; ЧТЕНИЕ ГОРИЗОНТАЛЬНОЙ копией (LD L,L): src-колонка лежит в ОЗУ
;; СМЕЖНО, адрес шагает (не port_y). ЗАПИСЬ ВЕРТИКАЛЬНОЙ (LD A,A):
;; port_y шагает вниз по видео-колонке. Режим меняется между read и
;; write (do_accel_block применяет один режим на весь блок).
ld l, l ; 0x6D гориз. копия (для ЧТЕНИЯ смежных)
ld a, (hl) ; read-блок: h смежных байт src -> буфер accel
ld a, a ; 0x7F верт. копия (для ЗАПИСИ колонки)
ld (de), a ; write-блок: буфер -> видео-колонка (port_y++)
ld b, b ; 0x40 стоп
;; src += sstride (следующая колонка источника)
ld a, l
add a, #0
bc_slo_imm = . - 1
ld l, a
ld a, h
adc a, #0
bc_shi_imm = . - 1
ld h, a
inc de ; dst += 1 (следующий x)
djnz bc_col
ei ; закрыть DI-окно
pop ix
;; callee-pop 5 байт (w,h,sstride:2,y0)
pop hl ; ret-адрес
pop af
pop af
inc sp
jp (hl)
__endasm;
}