/* * sprite_frame — сменить кадр атласа: запомнить (sx,sy) и пересчитать * кэш src = img + 4 + sx + sy*stride (адрес первого пикселя кадра). * * Кэш src — то, что реально использует блит (без чтения заголовка и * умножения на каждый кадр экрана); здесь единственное место, где * (sx,sy) конвертируются в адрес «дорогим» путём — одно 16-бит * умножение (__mulint; при sy < 256 он сам идёт коротким 8-итерационным * путём). Смена кадра — редкая операция рядом с блитом. * * Указатель НЕ разыменовывается — для W0-атласов пересчёт безопасен * без подключения страницы (вся арифметика на кэше stride из init). * * Была inline-функцией (только sx/sy+dirty) до появления кэша src * (2026-07-14, оптимизация B: blit 11.8К → ~10К тактов/спрайт). */ #include "../_bgi.h" #include void sprite_frame(sprite_t *s, int sx, int sy) { /* «Кадр не сменился» определяет src, НЕ (sx,sy): тикер анимации * двигает src, оставляя sx/sy нетронутыми, поэтому старые sx/sy * могут совпасть с запрошенными при уехавшем src. */ const uint8_t *src = (const uint8_t *)s->img + 4 + sx + (uint16_t)sy * s->stride; s->sx = sx; s->sy = sy; if (s->src != src) { s->src = src; s->flags |= _SPR_DIRTY; } }