/*
 * _gfx_blit_sprite — лин-ядро блита СПРАЙТА (кадр ≤ 64×64, см. sprite.h):
 * то же, что _gfx_blit_full, но БЕЗ split'а на полосы >256 (спрайт
 * заведомо ≤256 байт в строке) и с 8-битными w/h (дешевле передача
 * аргументов).  Один вызов _bgi_blit_rows_raw.  БЕЗ _bgi_begin/_bgi_end
 * и смены банка — вызывающий (sprite_update/putsprite) держит скобку и
 * банк 0x5C.  Проверок размера НЕТ (контракт ≤64 — в доке, не в коде).
 *
 * Клип по ЭКРАНУ остаётся (это функциональность — спрайты штатно уходят
 * за края): fast-path «целиком на экране» = 4 сравнения.
 *
 * ФОРМАТ getimage и параметры атласа
 * ----------------------------------
 * img указывает на getimage-буфер: 4-байтовый заголовок + пиксели.
 * Заголовок = uint16 width, uint16 height (little-endian):
 *   p[0]=width lo, p[1]=width hi, p[2]=height lo, p[3]=height hi.
 * Дальше (p+4) — пиксели ПОСТРОЧНО, по width байт на строку.
 *
 *   int img_w = p[0] | (p[1] << 8);
 * — это ПОЛНАЯ ширина картинки/ленты-атласа (склейка двух байтов
 * заголовка в 16-бит).  Используется как ШАГ между строками источника
 * (sstride): чтобы спуститься на строку ниже в буфере, надо прибавить к
 * адресу целую ширину картинки.  Для одиночного спрайта img_w == ширине
 * кадра; для ЛЕНТЫ-АТЛАСА (много кадров в ряд) img_w — ширина всей ленты
 * (> ширины кадра w), поэтому img_w остаётся int (лента может быть шире
 * 64, хотя КАДР ≤ 64).
 *
 *   (sx, sy) — смещение КАДРА (под-прямоугольника) ВНУТРИ картинки:
 * левый-верхний угол вырезаемого кадра в пикселях.  Для целого спрайта
 * sx = sy = 0.  Для кадра N горизонтальной ленты: sx = N*FRAME_W, sy = 0
 * (вертикальные атласы — sy).  Отсюда адрес первого пикселя кадра:
 *   src = p + 4  (пропустить заголовок)
 *       + sx     (сместиться на sx пикселей вправо в первой строке)
 *       + sy*img_w  (спуститься на sy строк — цикл сложений ниже, без
 *                    умножения: обычно sy == 0).
 */
#include "../_bgi.h"
#include <stdio.h>

void _gfx_blit_sprite(int x, int y, const void *img,
                      int sx, int sy, uint8_t w, uint8_t h)
{
    const uint8_t *p = (const uint8_t *)img;
    const uint8_t *src;
    uint16_t dst;
    int img_w = p[0] | (p[1] << 8);   /* ширина картинки/ленты = sstride */
    int cw = w, ch = h;               /* рабочие w,h кадра (для клипа) */

    if (x < 0 || y < 0 || x + cw > _bgi_maxx + 1 || y + ch > _bgi_maxy + 1) {
        if (x < 0) { sx -= x; cw += x; x = 0; }
        if (y < 0) { sy -= y; ch += y; y = 0; }
        if (x + cw > _bgi_maxx + 1) cw = _bgi_maxx + 1 - x;
        if (y + ch > _bgi_maxy + 1) ch = _bgi_maxy + 1 - y;
        if (cw <= 0 || ch <= 0) return;
    }


    /* Адрес первого пикселя кадра: заголовок(4) + sx вправо, затем sy
     * строк вниз (по img_w на строку) — циклом сложений, без __mulint
     * (обычно sy == 0: целый спрайт или горизонтальная лента). */
    src = p + 4 + sx;
    while (sy--)
        src += img_w;

    dst = _gfx_addr_base + x;

    _bgi_blit_rows_raw(src, (uint8_t *)dst, (uint8_t)cw, (uint8_t)ch,
                       img_w, (uint8_t)y);
}
