# 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:317–322]. --- ## 5.2 Режимы адресации видео-ОЗУ Видео-ОЗУ может адресоваться двумя способами — **спектрумовским** и **графическим** [IvanMak.txt:296–300]. Спектрумовский режим используется для 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:333–339]. Для записи в определённую пару спектрумовских блоков: 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:346–348]. ### 5.2.2 Графический режим адресации В графическом режиме видео-ОЗУ организовано как матрица **256 строк (rows) × 1024 байта** [IvanMak.txt:357–358]. Адресация: ``` 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]. **Работа с адресацией из программы:** ```asm ; Установить страницу 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:364–386]: | Бит | Страницы | Эффект | |-----|----------|--------| | 3 | `#58..#5F` | **Прозрачный цвет** — запись байта `#FF` игнорируется (для спрайтов) | | 2 | `#54..#57`, `#5C..#5F` | **Без тени** — запись только в VRAM, не в основное ОЗУ (для курсора мыши) | Биты 0 и 1 должны быть 0 для совместимости с будущими прошивками [IvanMak.txt:384–386]. --- ## 5.4 Теневая память (Shadow RAM) и двойная запись Видео-ОЗУ Спринтера является теневой памятью по отношению к основному ОЗУ [IvanMak.txt:317–322]. Видеоконтроллер **всегда** читает изображение из 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:405–469]. ### Режимы вывода | Режим | Разрешение | Цветов | Описание | |-------|-----------|--------|----------| | 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:448–469]. Для переключения видеорежима из программ используется функция DSS `SETVMOD` (50h) [DiskSyscalls.txt:345–349]: | 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:540–568]. | Адреса | Палитра | Назначение | |--------|---------|-----------| | `#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:545–547]. Выбор палитры для каждого квадратика — через биты 7..6 байта Mode1 [BIOS_v3.txt:348]. > **Примечание:** Architecture.txt упоминает всего 5 палитр (4 графические + > 1 текстовая), но IvanMak описывает все 8: 4 графические (0–3) и 4 текстовые > (4–7: бумага, символ, мерцание бумаги, мерцание символа) > [IvanMak.txt:547–548, 561–568]. --- ## 5.7 Структура VRAM в терминах BIOS При использовании BIOS распределение VRAM [IvanMak.txt:387–404]: | Адреса (линии) | Назначение | |----------------|-----------| | `#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`