Files
Sprinter-SDCC/libbgi/common/gfx_blit_part_noclip_vflip.c
T
snark13 3f45430454 libbgi: vflip-блиты для row-major картинок (шаг I.2 плана L9-INVERT)
gfx_blit_noclip_vflip / gfx_blit_part_noclip_vflip / gfx_blit_part_vflip.
Ассемблера не потребовалось: у row-major вертикальное зеркало — это порядок
строк, а он задаётся ЗНАКОМ src-страйда, который _bgi_blit_rows_raw и так
принимает знаковым и патчит SMC.  Даём адрес последней строки и -stride.

Клип у part_vflip свой: обрезка сверху экрана съедает НИЖНИЕ строки
источника, и первая строка обязана считаться от высоты ДО клипа (поймано
тестом — сначала формула брала уже укороченную).

tests/pageflip расширен до 8 проверок, все PASS в MAME.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-12 17:35:50 +03:00

33 lines
1.7 KiB
C

/*
* gfx_blit_part_noclip_vflip — под-прямоугольник картинки БЕЗ клипа,
* ЗЕРКАЛЬНО ПО ВЕРТИКАЛИ. Пара к gfx_blit_part_noclip; про механику
* зеркала (знак src-страйда) — см. gfx_blit_noclip_vflip.
*
* (sx,sy,w,h) задают кусок ИСТОЧНИКА в обычной системе координат, как у
* не-зеркального двойника: sy — верхняя строка куска. На экран этот кусок
* ложится перевёрнутым, (x,y) — левый верхний угол результата. Значит
* первой рисуется строка sy+h-1 источника.
*
* Тайловому слою это позволяет не трогать выбор куска атласа вообще:
* меняется только вызываемая функция и экранный y (его считает
* вызывающий — у него поле, у библиотеки экран).
*/
#include "../_bgi.h"
void gfx_blit_part_noclip_vflip(int x, int y, const void *img,
uint8_t sx, uint8_t sy, uint8_t w, uint8_t h)
{
const uint8_t *p = (const uint8_t *)img;
uint16_t stride = (uint16_t)(p[0] | (p[1] << 8));
const uint8_t *src;
if (!stride || !w || !h) return;
/* Стартуем с ПОСЛЕДНЕЙ строки куска и идём вверх. */
src = p + 4 + (uint16_t)(sy + h - 1) * stride + sx;
_bgi_begin();
_bgi_blit_rows_raw(src, (uint8_t *)(_gfx_addr_base + x),
w, h, -(int)stride, (uint8_t)y);
_bgi_end();
}