Files
Sprinter-SDCC/libbgi/common/gfx_scroll_h.c
T
snark13 64ce6339eb docs: справочники по железу Sprinter + правка gfx_scroll_h
- docs/new/ — сводные справочники (архитектура, BIOS, DSS, память,
  графика, акселератор, IRQ, порты, ввод, звук, известные баги);
- docs/Original/ — первоисточники, из которых они собраны (BIOS, Estex
  DSS, мануалы, описание акселератора), + Форум.doc/.docx в reference;
- libbgi/common/gfx_scroll_h.c — обход бага скролла при ширине >256
  (правка автора: шаг банды 255 и продвижение указателей на cw; старый
  вариант с 256 оставлен закомментированным с TODO);
- удалён applications/PoP/roomtest/hang_variants.png — рабочая раскладка
  из разбора позы виса, в репозитории ей не место.

Большие архивы (docs/extra ~568 МБ, docs/sources с вложенными git-репо
~68 МБ) в коммит НЕ включены — см. обсуждение.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-29 18:26:31 +03:00

71 lines
4.1 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* gfx_scroll_h — ГОРИЗОНТАЛЬНЫЙ скролл региона (mode-agnostic обёртка).
*
* Берёт чистый фон из НЕактивной (теневой) страницы и копирует его со
* сдвигом dx по X в активную (draw) страницу. Обе стороны — банк 0x50
* (GFX_BANK_NORMAL): запись бьёт VRAM + ОЗУ-копию, т.е. копия
* ОДНОВРЕМЕННО скроллит И «лечит» целевую страницу (старые спрайты
* затираются сдвинутым фоном; scroll-impl-guide.md §2).
*
* dx > 0 — сдвиг в сторону УВЕЛИЧЕНИЯ X (изображение едет вправо,
* открывается полоса слева); dx < 0 — влево (открывается справа);
* dx == 0 — чистая копия фона (полный heal целевой страницы). В обеих
* страницах остаёмся в пределах area. Открывшуюся |dx|-полосу НЕ
* заполняем — возвращаем её в *dirty (её дозаполняет вызывающий).
*
* РЕАЛИЗАЦИЯ — построчно, через _bgi_scroll_rows_raw (без страйдов, один
* OUT Port_Y на строку — на ~5-7% быстрее колоночного _bgi_scroll_cols_raw,
* которому на колонку нужен OUT и на чтение, и на запись). Горизонтальный
* сдвиг — чистая разница CPU-адресов src/dst (src_x vs dst_x), Port_Y для
* read и write один (одна строка). DI/EI бандами по 16 строк — ВНУТРИ
* leaf'а; он же режет высоту на банды и принимает h 1..256 (0=256), так что
* здесь делим только ширину >256 (лимит accel-блока). Перекрытий src/dst
* нет: стороны в разных страницах.
*/
#include "../include/sprite.h"
#include "../_bgi.h"
void gfx_scroll_h(const gfx_rect_t *area, int16_t dx, gfx_rect_t *dirty) {
uint8_t saved = gfx_get_bank();
uint16_t adx = (dx < 0) ? (uint16_t)(-dx) : (uint16_t)dx;
/* src-строка стартует правее на |dx| при сдвиге влево, dst — правее
* на dx при сдвиге вправо; так оба края остаются внутри area. */
uint16_t src_x = area->x + ((dx < 0) ? adx : 0);
uint16_t dst_x = area->x + ((dx > 0) ? adx : 0);
uint16_t w = area->w - adx; /* байт (пикселей) в строке */
uint8_t h = (uint8_t)area->h; /* строк (256 => 0 = 256 у leaf) */
uint16_t src = _gfx_addr_shadow_base + src_x;
uint16_t dst = _gfx_addr_base + dst_x;
gfx_set_bank(GFX_BANK_NORMAL);
_bgi_begin();
/* Ширина >256 байт — банды ≤256 (размер accel-блока, 0=256). Высоту и
* DI/EI-банды по 16 строк leaf делает сам (h: 0=256). Между бандами по
* ширине CPU-адрес двигаем на 256 (Port_Y выбирает строку). */
while (w) {
// Закомментированный блок должен работать правильно но не работает
// почему-то при w > 256 второй проход мусорит
// TODO: разобраться
// uint8_t cw = (w > 256) ? 256 : (uint8_t)w; /* 0 => 256 */
// _bgi_scroll_rows_raw(src, dst, cw, h, (uint8_t)area->y);
// src += 256; dst += 256;
// w -= (w > 256) ? 256 : w;
uint8_t cw = (w > 255) ? 255 : (uint8_t)w; /* 0 => 256 */
_bgi_scroll_rows_raw(src, dst, cw, h, (uint8_t)area->y);
src += cw; dst += cw; w -= cw;
}
_bgi_end();
gfx_set_bank(saved);
if (dirty) {
dirty->x = (dx >= 0) ? area->x : (int16_t)(area->x + area->w - adx);
dirty->y = area->y;
dirty->w = adx;
dirty->h = area->h;
}
}