Files
Sprinter-SDCC/docs/new/05-graphics.md
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

16 KiB
Raw Blame History

5. Графика и видеосистема

5.1 Общие сведения

Видеосистема Sprinter Sp2000 реализована в ППЛМ. Видео-ОЗУ — 256 КБ (512 КБ на некоторых платах [Architecture.txt:17]).

Параметр Значение
VRAM 256 КБ, независимая микросхема (не часть RAM SIMM)
Физические страницы #50..#5F (16 страниц × 16 КБ), фиксировано в железе
Видеорежимы ZX-40, ZX-80, GR-256-8, GR-16-16
Палитра 8 палитр × 256 цветов из 16 млн (RGB, BGR)
Видеовыход CGA-монитор, RGB, TV (SCART)

Теневая память (Shadow RAM): Видео-ОЗУ Спринтера является теневой памятью (§5.4). Программа управляет режимом записи через номер подключаемой страницы (§5.3): банк 0x50 пишет одновременно в VRAM и в основное ОЗУ; банк 0x54 пишет только в VRAM, не трогая ОЗУ. На экране всегда отображается содержимое VRAM, независимо от режима записи [IvanMak.txt:317322].


5.2 Режимы адресации видео-ОЗУ

Видео-ОЗУ может адресоваться двумя способами — спектрумовским и графическим [IvanMak.txt:296300]. Спектрумовский режим используется для Spectrum-совместимого вывода и загрузки знакогенераторов; графический — для всех остальных видеорежимов (320×256×256, 640×256×16, текст 80×32).

5.2.1 Спектрумовский режим адресации

В этом режиме VRAM разбивается на 32 блока по 8 КБ. Адрес блока задаётся через порт RGADR (PORT_Y, #89):

Бит Назначение
4..0 Номер блока (0..31)
5 Не используется
6 Запрет вывода (1 = отключить спектрумовский вывод)
7 Разрешение 16-КБ страницы (1 = два блока в #4000..#7FFF)

Бит 0 RGADR вместе с битом 1 порта #7FFD определяет чётность подключаемого блока VRAM: чётный RGADR → блок N в #4000..#5FFF, блок N+1 в #C000..#DFFF; нечётный → наоборот [IvanMak.txt:333339].

Для записи в определённую пару спектрумовских блоков:

  1. Записать номер блока в RGADR (OUT (#89),A).
  2. Убедиться, что в окне (#4000 или #C000) стоит подходящая страница основного ОЗУ (любая, кроме #50..#5F).
  3. Чтение/запись по спектрумовским адресам (#4000..#5FFF, #C000..#DFFF) попадает в VRAM через текущий блок.

Выключение спектрумовского вывода: Если программа не использует Spectrum-совместимую графику, RGADR рекомендуется установить в #C0..#FF (бит 6 = 1). В этом случае вывод в VRAM через спектрумовский режим не производится [IvanMak.txt:346348].

5.2.2 Графический режим адресации

В графическом режиме видео-ОЗУ организовано как матрица 256 строк (rows) × 1024 байта [IvanMak.txt:357358]. Адресация:

VRAM_адрес = (RGADR << 10) | (Z80_A[9:0])
  где RGADR[7:0] = Y (номер строки, 0..255)
      Z80_A[9:0] = X (смещение в строке, 0..1023)

Страницы #50..#5F при маппинге в любое окно Z80 включают графическую адресацию. При этом младшие 4 бита номера страницы не влияют на адрес памяти, а задают подрежим вывода (§5.3).

Важная особенность: Z80-адрес внутри окна (биты A[13:10] для окна W3) игнорируется — весь 16-КБ диапазон окна отображает одну и ту же строку, выбранную RGADR. Доступ к другим строкам — только через смену RGADR. Это означает, что утверждение из SprinterGraphics programming.txt о доступе к строкам 18..31 через адреса #C400..#FC00 неверно.

Структура 1-КБ строки (1024 байта):

Смещение в строке Назначение
#000..#13F (0..319) Экранная страница 0 (первые 320 байт)
#140..#27F (320..639) Экранная страница 1 (следующие 320 байт)
#280..#3FF (640..1023) Не используется / данные палитры

Две экранные страницы (0 и 1) переключаются битом 0 порта RGMOD [IvanMak.txt:409].

Работа с адресацией из программы:

; Установить страницу VRAM (0x50) в W3
IN    A, (#E2)          ; сохранить текущую W3
LD    (old_page), A
LD    A, #50
OUT   (#E2), A          ; W3 = VRAM страница 0x50

; Выбрать строку Y
LD    A, Y              ; Y = 0..255
OUT   (#89), A          ; RGADR = Y

; Чтение/запись пикселя (X,Y) для экранной страницы 0
LD    HL, #C000 + X     ; X = 0..319
LD    (HL), colour      ; запись байта пикселя

; Восстановить страницу
LD    A, (old_page)
OUT   (#E2), A

5.3 Подрежимы вывода (страницы #50..#5F)

Биты 2 и 3 номера страницы (из диапазона #50..#5F) задают подрежимы вывода [IvanMak.txt:364386]:

Бит Страницы Эффект
3 #58..#5F Прозрачный цвет — запись байта #FF игнорируется (для спрайтов)
2 #54..#57, #5C..#5F Без тени — запись только в VRAM, не в основное ОЗУ (для курсора мыши)

Биты 0 и 1 должны быть 0 для совместимости с будущими прошивками [IvanMak.txt:384386].


5.4 Теневая память (Shadow RAM) и двойная запись

Видео-ОЗУ Спринтера является теневой памятью по отношению к основному ОЗУ [IvanMak.txt:317322]. Видеоконтроллер всегда читает изображение из VRAM для вывода на экран; основное ОЗУ в формировании изображения не участвует. Однако при записи через графические банки #50..#5F поведение зависит от выбранного подрежима:

  • Банк 0x50 (normal): запись идёт одновременно в VRAM и в соответствующую область основного ОЗУ. Чтение из того же Z80-адреса возвращает данные из основного ОЗУ, а не из VRAM — VRAM для процессора на чтение не видна.
  • Банк 0x54 (noshadow): запись — только в VRAM, основное ОЗУ не изменяется. Чтение — из основного ОЗУ (там хранится «фон»).
  • Банк 0x58 (transparent): как normal, но байт #FF не пишется.
  • Банк 0x5C (sprite): transparent + noshadow.
  • Обычные банки (не #50..#5F): никакого доступа к VRAM нет, чтение/запись идут напрямую в основное ОЗУ.

Зачем это нужно:

  1. Восстановление после переключения видеорежима: данные в основном ОЗУ остаются нетронутыми, так что при возврате в графический режим экран можно восстановить без перерисовки [IvanMak.txt:325].
  2. Heal спрайтов (libbgi): фон, на который был выведен спрайт в банке GFX_BANK_SPRITE (0x5C, без тени), остался в основном ОЗУ. После перемещения спрайта фон копируется из основного ОЗУ обратно в VRAM (операция heal), стирая спрайт.
  3. Курсор мыши без сохранения/восстановления: временный вывод через GFX_BANK_NOSHADOW (0x5C) — в основном ОЗУ данные под курсором не портятся, достаточно при следующем обновлении просто перерисовать фон.

Режимы записи (см. §5.3):

Режим Пишет в VRAM Пишет в осн. ОЗУ Применение
0x50 (normal) Да Да Обычный вывод
0x54 (noshadow) Да Нет временные эффекты
0x58 (transparent) Да (кроме #FF) Да Спрайты с прозрачностью без heal
0x5C (sprite) Да (кроме #FF) Нет Курсор, спрайты (прозрачность + heal)

5.5 Видеорежимы

Система поддерживает независимую установку режима для каждого квадратика 8×8 (или 16×8 для 640-режимов) на экране [IvanMak.txt:405469].

Режимы вывода

Режим Разрешение Цветов Описание
ZX-40 320×256 16 Текстовый 40×32, Spectrum-совместимый
ZX-80 640×256 16 Текстовый 80×32, до 36 знакогенераторов
GR-256-8 320×256 256 Графический, 1 байт/пиксель
GR-16-16 640×256 16 Графический, 4 бита/пиксель

Формат пикселей

GR-256-8 (320×256×256): один байт = один пиксель. Строка содержит 320 байт для экранной страницы 0 (смещения #000..#13F) и 320 байт для страницы 1 (#140..#27F). Полный экран: 320 × 256 = 81 920 байт на страницу.

GR-16-16 (640×256×16): один байт = два пикселя: младший полубайт — левый/первый пиксель, старший — правый/второй. Строка содержит 320 байт на экранную страницу, что даёт 640 пикселей (320 × 2). Структура строки та же: 320 байт на страницу 0, 320 на страницу 1.

Установка режима

Режим задаётся 4 байтами Mode0..Mode3 в области режимов VRAM (#0300..#039F). Полное описание формата Modei — [IvanMak.txt:448469].

Для переключения видеорежима из программ используется функция DSS SETVMOD (50h) [DiskSyscalls.txt:345349]:

A (режим) Описание
02h Текстовый 40×32×16
03h Текстовый 80×32×16
81h Графический 320×256×256
82h Графический 640×256×16

B — страница экрана (0/1). Вызов: RST 10h с C=50h. Флаг C = ошибка (например, режим не поддерживается данным монитором).


5.6 Палитра

8 палитр по 256 цветов, каждая занимает 1 КБ в VRAM по адресам #03E0..#03FE [IvanMak.txt:540568].

Адреса Палитра Назначение
#03E0..#03E2 Граф. 0 Графические режимы
#03E4..#03E6 Граф. 1 —//—
#03E8..#03EA Граф. 2 —//—
#03EC..#03EE Граф. 3 —//—
#03F0..#03F2 Текст. 4 Цвет бумаги
#03F4..#03F6 Текст. 5 Цвет символа
#03F8..#03FA Текст. 6 Цвет мерцания бумаги
#03FC..#03FE Текст. 7 Цвет мерцания символа

Каждый четвёртый байт в каждой палитре не используется — не может попасть на ЦАП [IvanMak.txt:545547]. Выбор палитры для каждого квадратика — через биты 7..6 байта Mode1 [BIOS_v3.txt:348].

Примечание: Architecture.txt упоминает всего 5 палитр (4 графические + 1 текстовая), но IvanMak описывает все 8: 4 графические (0–3) и 4 текстовые (4–7: бумага, символ, мерцание бумаги, мерцание символа) [IvanMak.txt:547548, 561568].


5.7 Структура VRAM в терминах BIOS

При использовании BIOS распределение VRAM [IvanMak.txt:387404]:

Адреса (линии) Назначение
#0000..#003F Спектрумовский экран (блоки 0..1)
#0040..#017F Первый графический экран (блоки 2..11)
#0180..#02BF Второй графический экран (блоки 12..21)
#02C0..#02FF Знакогенераторы текстового режима
#0300..#039F Область описания режимов экрана
#03A0..#03DF Зарезервировано
#03E0..#03FF Палитра

5.8 Заблуждения и неподтверждённое

Миф о строках 18–31: В документе SprinterGraphics programming.txt утверждается, что после выбора строки Y через RGADR, по адресам #C400..#FC00 доступны строки Y+1..Y+15 (с шагом 1 КБ). В эмуляторе MAME это не работает — весь 16-КБ диапазон страницы #50..#5F отображает только строку Y, независимо от бит A[13:10] адреса Z80. Требуется проверка на реальном Sprinter Sp2000.


5.9 Кросс-ссылки

  • Палитра и видеорежимы BIOS: 02-bios.md §2.7
  • SETVMOD (DSS): 03-dss.md §3.10
  • Акселератор: 06-accel.md
  • Быстрое ОЗУ и конфликт с акселератором: 04-memory.md §4.6
  • Порты RGADR/RGMOD: 11-ports.md
  • Баги акселератора: 12-bugs.md
  • Проектные документы: sprite-api-design.md, accel-fill-budget.md