/* * _gfx_blit_sprite_noclip — блит спрайта БЕЗ клипа по экрану. Как * _gfx_blit_sprite, но клип-математики нет ВООБЩЕ (не скип проверки — * кода нет физически): приложение ГАРАНТИРУЕТ, что спрайт целиком на * экране (флаг gfx_sprite_clip(0)). Отдельная функция, а не ветка в * _gfx_blit_sprite: без клип-кода SDCC тесней раскладывает регистры * (меньше спиллов) — отсюда полный выигрыш ~+19% на анимации (замер * A/B на examples/balls 2026-07-12), а не только скип сравнений. * * ВНИМАНИЕ: запись за край экрана портит соседнюю память (Port_Y за 256 * заворачивается наверх, x за 320 — в соседнюю строку/страницу; см. * tests/spriteclip). Вызывать только когда спрайт заведомо в пределах. * * Формат img/img_w/sx/sy — как в _gfx_blit_sprite (getimage-заголовок + * лента-атлас). БЕЗ _bgi_begin/_bgi_end и смены банка (держит вызывающий). */ #include "../_bgi.h" void _gfx_blit_sprite_noclip(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; int img_w = p[0] | (p[1] << 8); /* ширина картинки/ленты = sstride */ /* sy*img_w умножением (__mulint, O(1) ~300Т): вертикальные ленты * атласов сделали sy != 0 нормой — старый цикл сложений был O(sy), * до ~64К тактов на блит кадра 11 (профиль rpgwalk 2026-07-13). * if (sy): горизонтальные ленты/одиночные спрайты (sy == 0) не * платят и за умножение. */ src = p + 4 + sx; if (sy) src += (uint16_t)sy * (uint16_t)img_w; _bgi_blit_rows_raw(src, (uint8_t *)(_gfx_addr_base + x), w, h, img_w, (uint8_t)y); }