libbgi: chunked-заливки на мульти-триггере акселератора + сплит rectfill

Семантика FSM акселератора вскрыта по драйверу MAME (sprinter.cpp) и
подтверждена экспериментами в MAME (tests/accfill): армирование живёт до
следующего accel-опкода (мульти-триггер работает); под армированием
триггерит ЛЮБОЙ non-M1 доступ к памяти (fetch операнда djnz/out!);
вертикальный Fill двигает Port_Y и не возвращает; размер блока переживает
LD B,B.  Детали: memory/accel_multitrigger_fill.

- _bgi_clear_raw: 20 DI-скобок по 16 колонок вместо полного брекета на
  каждую из 320 колонок; армирование размера один раз на скобку.
- _gfx_rectfill256 разделён: диспетчер (проверка ориентации ~160-245Т,
  break-even |w-h| >= ~4) + leaf'ы _gfx_recthfill256/_gfx_rectvfill256
  для прямого вызова, когда форма известна заранее.
- Leaf'ы: чанки <=16 линий одной скобкой (~54-56Т/линию против ~250Т у
  per-line варианта); счётчик чанков precompute'ится в байт-регистр
  (dec e/jr nz ~46Т/чанк вместо 16-бит арифметики в IX-слотах
  ~173Т/чанк); хвост — отдельная скобка со своим армированием (CBL-ISR
  в окне EI армирует акселератор своим размером — не выносить).
- getpixel/putpixel/_bgi_read: уборка мёртвого закомментированного кода.
- tests/accfill: регресс chunked-заливок (B0 clear, B1 vert 1+3 чанка,
  B2 horz чанк+хвост, полноширинный bar 320x8 — путь w>=256).

Прежние реализации сохранены под #if 0 для отката/сравнения.
Проверено в MAME (все PASS); семантика эмуляции — перепроверить на
реальном Sprinter.  size-baseline: accfill добавлен, gfx_demo +54 Б
(обвязка диспетчера), остальные без роста.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-10 17:41:49 +03:00
parent e553e5e6c9
commit 2c414da465
11 changed files with 617 additions and 49 deletions
+49 -1
View File
@@ -1,12 +1,59 @@
/*
* _bgi_clear_raw — залить всё поле 320×256 цветом color, mode 0x81.
* 320 вертикальных Fill-burst'ов (по колонке 256 строк), Port_Y=0.
*
* Chunked-схема (v2, 2026-07-10): 20 DI-скобок по 16 колонок (256 строк
* каждая) — армирование размера один раз на скобку, на колонку только
* ре-арм LD E,E + выстрел (см. _gfx_rectfill256.c и
* memory/accel_multitrigger_fill; проверено в MAME tests/accfill).
* Окно DI на чанк ≈ 0.6 мс (16×256 байт) — CBL/IM2 живут.
* Вертикальный Fill двигает Port_Y — re-OUT 0 перед каждой колонкой.
*
* Register-only asm, без глобального скретча. W3-naive: вызывающий
* обрамляет _bgi_begin/_bgi_end. color → A (__sdcccall(1)).
*/
#include "../_bgi.h"
void _bgi_clear_raw(uint8_t color) __naked
{
__asm
.globl __gfx_addr_base
ld c, a ; C = цвет
ld hl, (__gfx_addr_base) ; HL = база draw-страницы
ld d, #0 ; y0 = 0
ld e, #20 ; 20 чанков × 16 колонок = 320
clr_chunk:
di
;; Армирование размера НЕ выносить из цикла (экономия ~0.1%):
;; в окне EI между чанками CBL-ISR сам армирует акселератор
;; своим размером блока каждый чанк обязан армировать заново.
ld d, d ; 0x52 режим размера блока (no-op для D)
ld a, #0 ; размер 256 (конвенция акселератора)
ld b, b ; выключить размер сохранён
ld b, #16 ; колонок в чанке
clr_col:
ld a, d
out (#0x89), a ; Port_Y = 0 (vertical Fill его сдвинул)
ld e, e ; 0x5B вертикальный Fill (no-op для E)
ld a, c
ld (hl), a ; выстрел: колонка 256 строк
ld b, b ; выключить (перед djnz fetch смещения!)
inc hl ; следующая колонка
djnz clr_col
ei ; окно для прерываний между чанками
dec e
jr NZ, clr_chunk
ret
__endasm;
}
#if 0
/* ================================================================
* Старый вариант (до 2026-07-10): полный брекет (DI+арм размера+
* режим+выстрел+выкл+EI) на КАЖДУЮ из 320 колонок. Оставлен
* закомментированным для отката/сравнения.
* ================================================================ */
void _bgi_clear_raw(uint8_t color) __naked
{
__asm
@@ -39,3 +86,4 @@ void _bgi_clear_raw(uint8_t color) __naked
jr _clear_cyc0
__endasm;
}
#endif