3f45430454
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>
53 lines
3.0 KiB
C
53 lines
3.0 KiB
C
/*
|
|
* gfx_blit_part_vflip — под-прямоугольник картинки С КЛИПОМ по экрану,
|
|
* ЗЕРКАЛЬНО ПО ВЕРТИКАЛИ. Пара к gfx_blit_part; механика зеркала — см.
|
|
* gfx_blit_noclip_vflip (знак src-страйда).
|
|
*
|
|
* Клип здесь СВОЙ, а не через _gfx_blit_full: общее ядро режет источник в
|
|
* прямом порядке строк, а у зеркала обрезка сверху экрана съедает НИЖНИЕ
|
|
* строки источника — считать это внутри общего ядра дороже, чем восемь
|
|
* строк арифметики здесь (функция и так вызывается только у края экрана,
|
|
* в тайловом слое основной путь — noclip-двойники).
|
|
*
|
|
* Соответствие строк: экранная (y + i) <- источник (sy + h - 1 - i).
|
|
* Значит обрезка сверху (y < 0) сдвигает старт по i, а обрезка снизу
|
|
* просто укорачивает h.
|
|
*/
|
|
#include "../include/gfx.h"
|
|
#include "../_bgi.h"
|
|
|
|
void gfx_blit_part_vflip(int x, int y, const void *img,
|
|
int sx, int sy, int w, int h)
|
|
{
|
|
const uint8_t *p = (const uint8_t *)img;
|
|
uint16_t stride = (uint16_t)(p[0] | (p[1] << 8));
|
|
int skip;
|
|
int h0 = h; /* высота ДО клипа — от неё считается первая
|
|
* строка источника (h ниже укорачивается) */
|
|
|
|
if (!stride || w <= 0 || h <= 0) return;
|
|
|
|
/* --- клип по X: источник сдвигается вместе с экраном --- */
|
|
if (x < 0) { sx -= x; w += x; x = 0; }
|
|
if (x + w > GFX_WIDTH) w = GFX_WIDTH - x;
|
|
if (w <= 0) return;
|
|
|
|
/* --- клип по Y: сверху съедаются НИЖНИЕ строки источника --- */
|
|
if (y < 0) { skip = -y; h -= skip; y = 0; } else { skip = 0; }
|
|
if (y + h > GFX_HEIGHT) h = GFX_HEIGHT - y;
|
|
if (h <= 0) return;
|
|
|
|
/* Полосы шире одного accel-блока режет вызывающий у noclip-двойников;
|
|
* здесь ширина приходит от тайла (≤ 64), поэтому хватает одной. */
|
|
if (w > 255) w = 255;
|
|
|
|
_bgi_begin();
|
|
/* Экранная строка (y+i) <- источник (sy + h0 - 1 - i). Обрезка сверху
|
|
* сдвигает старт на skip строк ВНИЗ по источнику, обрезка снизу только
|
|
* укорачивает h и первой строки не касается. */
|
|
_bgi_blit_rows_raw(p + 4 + (uint16_t)(sy + h0 - 1 - skip) * stride + (uint16_t)sx,
|
|
(uint8_t *)(_gfx_addr_base + x),
|
|
(uint8_t)w, (uint8_t)h, -(int)stride, (uint8_t)y);
|
|
_bgi_end();
|
|
}
|