/*
 * 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 <sprite.h>

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;
    }
}
