/* * gfx_scroll_v — ВЕРТИКАЛЬНЫЙ скролл региона (mode-agnostic обёртка). * * Симметрична gfx_scroll_h, но сдвиг по Y. Берёт чистый фон из НЕактивной * (теневой) страницы и копирует его со сдвигом dy по Y в активную (draw) * страницу. Банк 0x50: копия = скролл + heal целевой страницы (старые * спрайты затираются сдвинутым фоном; см. gfx_scroll_h / guide §2). * * dy > 0 — сдвиг в сторону УВЕЛИЧЕНИЯ Y (изображение едет вниз, * открывается полоса сверху); dy < 0 — вверх (открывается снизу); * dy == 0 — чистая копия (полный heal). Открывшуюся |dy|-полосу НЕ * заполняем — возвращаем в *dirty. * * РЕАЛИЗАЦИЯ — колонками, через _bgi_scroll_cols_raw (вертикальный режим * accel): колонку читаем с Port_Y=ys, пишем с Port_Y=yd (= ys+dy) — сдвиг * по Y без буфера-посредника (STOP между read и write делает промежуточный * OUT Port_Y безопасным; см. шапку leaf'а). Один проход, вдвое быстрее * прежнего grab→blit-через-буфер. Ширину >255 режем на банды колонок * (leaf сам делит их на DI-скобки по 16). Высота колонки h = area->h−|dy| * (≤256, 0=256 у accel). Перекрытия src/dst нет: стороны в разных страницах. */ #include "../include/sprite.h" #include "../_bgi.h" void gfx_scroll_v(const gfx_rect_t *area, int16_t dy, gfx_rect_t *dirty) { uint8_t saved = gfx_get_bank(); uint16_t ady = (dy < 0) ? (uint16_t)(-dy) : (uint16_t)dy; /* Строку чтения (ys) сдвигаем вниз на |dy| при сдвиге вверх, строку * записи (yd) — вниз на dy при сдвиге вниз; края в пределах area. */ uint8_t ys = (uint8_t)(area->y + ((dy < 0) ? ady : 0)); uint8_t yd = (uint8_t)(area->y + ((dy > 0) ? ady : 0)); uint16_t hb = area->h - ady; /* строк к переносу (≤256) */ if (hb) { /* 0 = переносить нечего */ uint8_t hblk = (uint8_t)hb; /* размер accel-блока: 256 => 0 */ uint16_t w = area->w; uint16_t src = _gfx_addr_shadow_base + area->x; uint16_t dst = _gfx_addr_base + area->x; gfx_set_bank(GFX_BANK_NORMAL); _bgi_begin(); /* >255 колонок — банды (leaf 8-битный по числу колонок; 0=выход, * поэтому ≤255, а не 256). Высота колонки одна на весь проход. */ while (w) { uint8_t cw = (w > 255) ? 255 : (uint8_t)w; _bgi_scroll_cols_raw(src, dst, cw, hblk, ys, yd); src += cw; dst += cw; w -= cw; } _bgi_end(); gfx_set_bank(saved); } if (dirty) { dirty->x = area->x; dirty->y = (dy >= 0) ? area->y : (int16_t)(area->y + area->h - ady); dirty->w = area->w; dirty->h = ady; } }