Files
Sprinter-SDCC/libbgi/common/_gfx_blit_full.c
T
snark13 72ce66275e libbgi: спрайтовый движок v2 + accel-блит/heal leaf'ы + noclip-путь
Спрайтовая графика поверх accel block-copy (docs/sprite-api-design.md):

- Ядро блиттинга: leaf'ы _bgi_blit_rows_raw (dst фикс, только src-страйд) /
  _bgi_copy_rows_raw (getimage) / _bgi_heal_rows_raw (src==dst). DI один на
  спрайт (санкция: малый спрайт под одним DI аудио не рвёт); src[0]-фикс
  снят (точная MAME подавляет CPU-байт триггера записи — на железе
  перепроверить; для heal был избыточен и снят безусловно).
- Общие bracket-free ядра _gfx_blit_full/_gfx_heal_full (полная ширина:
  клип по экрану + split >256 для putimage) + лин _gfx_blit_sprite/
  _gfx_heal_sprite (кадр ≤64, без split, 8-бит w/h) + noclip-варианты
  (клип-кода нет → полный codegen-win).  Имя *_full (не *_clip) — «clip»
  двусмысленно (sprite-ядра тоже клипуют; различитель — ширина/split).
- Движок retained-модели <sprite.h>: sprite_init/update/flip + inline
  move/frame/show/hide/touch; drawn[2] per-page внутри структуры; кадр —
  двухпроходно heal ВСЕ -> блит ВСЕ под одной W3-скобкой/банком на проход.
- Флаг gfx_sprite_clip(on/off): приложение, само следящее за границами,
  отключает клип (~+19% на анимации; диспетч пока через if — funcptr далее).
- putsprite/movesprite/gfx_blit/putimage(COPY)/getimage переведены на ядро.

Тесты: examples/balls (движок, дабл-буфер, boundary-тест клипа),
tests/sprites (RAM PASS, клип 4 края, атлас), tests/blitw (trig-leak),
tests/spriteclip (hardware-probe: железо НЕ режет за краем -> клип нужен),
tests/blitperf, tests/gfxbanks. size-baseline обновлён (53 программы).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-12 21:51:52 +03:00

58 lines
2.7 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* _gfx_blit_full — bracket-free ядро блита под-прямоугольника картинки
* getimage-формата (см. gfx_blit_part). Клип по экрану + нарезка на
* полосы ≤256 + вызов accel-leaf'а _bgi_copy_rows_raw. БЕЗ _bgi_begin/
* _bgi_end и БЕЗ смены банка — вызывающий обязан замапить W3 (_bgi_begin)
* и выставить нужный _gfx_bank ДО вызова.
*
* Вынесено из gfx_blit_part (2026-07-12) ради batch-пасса спрайтового
* движка v2: sprite_update держит одну W3-скобку и один банк на ВЕСЬ
* проход, вызывая это ядро в цикле по спрайтам (амортизация обвязки —
* см. docs/sprite-api-design.md §9.1). gfx_blit_part теперь = _bgi_begin
* + это ядро + _bgi_end.
*
* Clip fast-path: если прямоугольник целиком на экране — 4 сравнения
* вместо полного пути коррекции краёв (TODO «клип fast-path»).
*/
#include "../_bgi.h"
void _gfx_blit_full(int x, int y, const void *img,
int sx, int sy, int w, int h)
{
const uint8_t *p = (const uint8_t *)img;
const uint8_t *src;
uint16_t dst;
int img_w;
/* img_w — ПОЛНАЯ ширина картинки/ленты из заголовка getimage
* (p[0]=lo, p[1]=hi); это шаг между строками источника (sstride).
* sx/sy — смещение кадра внутри картинки (атлас). Подробный разбор
* формата и sx/sy — в common/_gfx_blit_sprite.c. */
img_w = p[0] | (p[1] << 8);
/* Клип по экрану — только если хоть один край вылезает. */
if (x < 0 || y < 0 || x + w > _bgi_maxx + 1 || y + h > _bgi_maxy + 1) {
if (x < 0) { sx -= x; w += x; x = 0; }
if (y < 0) { sy -= y; h += y; y = 0; }
if (x + w > _bgi_maxx + 1) w = _bgi_maxx + 1 - x;
if (y + h > _bgi_maxy + 1) h = _bgi_maxy + 1 - y;
if (w <= 0 || h <= 0) return;
}
/* src = img + 4 + sy*img_w + sx — без __mulint (обычно sy == 0). */
src = p + 4 + sx;
while (sy--)
src += img_w;
dst = _gfx_addr_base + x;
while (w > 256) {
_bgi_blit_rows_raw(src, (uint8_t *)dst, 0 /* =256 */, (uint8_t)h,
img_w, (uint8_t)y);
src += 256;
dst += 256;
w -= 256;
}
_bgi_blit_rows_raw(src, (uint8_t *)dst, (uint8_t)w, (uint8_t)h,
img_w, (uint8_t)y);
}