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

280 lines
16 KiB
Markdown
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.
# 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].
**Работа с адресацией из программы:**
```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: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`