Files
Sprinter-SDCC/libbgi/common/_gfx_blit_full.c
T
snark13 0eec977630 libbgi: sy*img_w умножением вместо O(sy)-цикла — rpgwalk 24 → стабильные 48 fps
Профилирование rpgwalk в dev-MAME (watchpoint на OUT-маркеры +
totalcycles) показало: blit 8 спрайтов ел 17 мс из 20.5 — 85% в цикле
`while (sy--) src += img_w;` blit-обёрток (писался под «обычно sy==0»,
а вертикальные ленты атласов дают sy до 176 → до 64К тактов на кадр).

Фикс: src += sy*img_w через __mulint (O(1); __mul16 адаптивен — при
sy < 256 крутит 8 итераций, ~500Т) + if (sy): горизонтальные ленты и
одиночные спрайты не платят и за умножение.  Blit: 45К → 11.8К
тактов/спрайт.

Замерен бюджет кадра (docs/sprite-api-design.md §9д): кадр 48.83 Гц =
430080 тактов @21МГц; спрайт 16×16 ≈ 26К (тик 7.3К + heal 6.4К +
blit 11.8К) → лимит стабильных 48 fps = 14 спрайтов (15 — 94% кадров,
16 — на грани).  FPS-плашка bar+outtextxy стоит ~210К (полкадра!) —
HUD рисовать putimage-заготовкой.

examples/rpgwalk/rpgprof.c — профилировочная копия демо: визуальный
профайлер (цвет бордера по секциям кадра) + маркеры для тактового
профайла через wpiset дебаггера (рецепт в шапке и §9д).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-13 21:54:37 +03:00

59 lines
2.8 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; sy*img_w умножением (__mulint,
* O(1)) — цикл сложений был O(sy), см. _gfx_blit_sprite.c. */
src = p + 4 + sx;
if (sy)
src += (uint16_t)sy * (uint16_t)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);
}