Files
Sprinter-SDCC/tests/scroll/scroll.c
T
snark13 e2730f78e0 gfx_scroll_v: колоночный accel-проход без буфера-посредника + тест scroll
Вертикальный скролл перестал ходить через строку-буфер на стеке: колонку
читаем с Port_Y=ys, пишем с Port_Y=yd, а STOP между read- и write-триггером
делает промежуточный OUT Port_Y безопасным.  Один проход вместо
grab→blit-через-буфер.

Справочник libc приведён в соответствие (там же строка про новую точку
входа cbl_open_silence).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-20 21:59:28 +03:00

140 lines
3.6 KiB
C

/* Побайтовый регресс gfx_scroll_h/gfx_scroll_v.
* Источник — неактивная page 1, приёмник — draw page 0. */
#include <graphics.h>
#include <gfx.h>
#include <sprite.h>
#define AX 10
#define AY 24
#define AW 300 /* проверяет разбиение ширины 255+45 */
#define AH 160
#define DIRT 0x31
static uint8_t pattern(int x, int y)
{
return (uint8_t)(0x40 + ((x * 3 + y * 5) & 0x3f));
}
static void draw_source(void)
{
int x, y;
for (y = AY; y < AY + AH; y++)
for (x = AX; x < AX + AW; x++)
putpixel(x, y, pattern(x, y));
}
static void clear_target(void)
{
setfillstyle(SOLID_FILL, DIRT);
bar(0, 0, 319, 255);
}
static uint8_t rect_eq(const gfx_rect_t *r, int x, int y, int w, int h)
{
return r->x == x && r->y == y && r->w == w && r->h == h;
}
static uint8_t check_h(int dx)
{
gfx_rect_t a = { AX, AY, AW, AH }, d;
int x, y, sx;
clear_target();
gfx_scroll_h(&a, dx, &d);
if (dx > 0) {
if (!rect_eq(&d, AX, AY, dx, AH)) return 0;
} else if (dx < 0) {
if (!rect_eq(&d, AX + AW + dx, AY, -dx, AH)) return 0;
} else if (!rect_eq(&d, AX, AY, 0, AH)) return 0;
for (y = AY; y < AY + AH; y++)
for (x = AX; x < AX + AW; x++) {
sx = x - dx;
if (sx >= AX && sx < AX + AW) {
if ((uint8_t)getpixel(x, y) != pattern(sx, y)) return 0;
} else if ((uint8_t)getpixel(x, y) != DIRT) return 0;
}
return 1;
}
static uint8_t check_v(int dy)
{
gfx_rect_t a = { AX, AY, AW, AH }, d;
int x, y, sy;
clear_target();
gfx_scroll_v(&a, dy, &d);
if (dy > 0) {
if (!rect_eq(&d, AX, AY, AW, dy)) return 0;
} else if (!rect_eq(&d, AX, AY + AH + dy, AW, -dy)) return 0;
for (y = AY; y < AY + AH; y++)
for (x = AX; x < AX + AW; x++) {
sy = y - dy;
if (sy >= AY && sy < AY + AH) {
if ((uint8_t)getpixel(x, y) != pattern(x, sy)) return 0;
} else if ((uint8_t)getpixel(x, y) != DIRT) return 0;
}
return 1;
}
static uint8_t check_limits(void)
{
gfx_rect_t a = { -5, -7, 25, 27 }, d;
gfx_scroll_h(&a, 40, &d);
if (!rect_eq(&d, 0, 0, 20, 20)) return 0;
gfx_scroll_v(&a, -40, &d);
return rect_eq(&d, 0, 0, 20, 20);
}
static uint8_t check_source(void)
{
int x, y;
gfx_set_draw_page(1);
for (y = AY; y < AY + AH; y++)
for (x = AX; x < AX + AW; x++)
if ((uint8_t)getpixel(x, y) != pattern(x, y)) {
gfx_set_draw_page(0);
return 0;
}
gfx_set_draw_page(0);
return 1;
}
static void say(int y, const char *name, uint8_t ok)
{
setcolor(WHITE); outtextxy(8, y, (char *)name);
setcolor(ok ? GREEN : RED); outtextxy(232, y, ok ? (char *)"PASS" : (char *)"FAIL");
}
void main(void)
{
uint8_t t[7], i;
initgraph();
gfx_set_bank(GFX_BANK_NORMAL);
gfx_set_draw_page(1); draw_source();
gfx_set_draw_page(0);
t[0] = check_h(8);
t[1] = check_h(-13);
t[2] = check_v(9);
t[3] = check_v(-11);
t[4] = check_limits();
t[5] = check_h(0);
t[6] = check_source();
clear_target();
say(40, "H +8, wide", t[0]);
say(56, "H -13, wide", t[1]);
say(72, "V +9, wide", t[2]);
say(88, "V -11, wide", t[3]);
say(104, "clip/full dirty", t[4]);
say(120, "H zero/full copy", t[5]);
say(136, "source intact", t[6]);
for (i = 0; i < 7 && t[i]; i++) { }
setcolor(WHITE);
outtextxy(8, 160, i == 7 ? (char *)"ALL PASS" : (char *)"SOME FAILED");
for (;;) { }
}