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>
This commit is contained in:
2026-07-29 18:26:31 +03:00
parent 1214785a56
commit 64ce6339eb
32 changed files with 23762 additions and 3 deletions
+279
View File
@@ -0,0 +1,279 @@
# 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`