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>
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
PROJ_ROOT := $(abspath $(CURDIR)/../..)
|
||||
EXAMPLE := scroll
|
||||
EXTRA_FLAGS ?= --gfx 256 --safe
|
||||
include $(PROJ_ROOT)/app.mk
|
||||
@@ -0,0 +1,139 @@
|
||||
/* Побайтовый регресс 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 (;;) { }
|
||||
}
|
||||
Reference in New Issue
Block a user