64ce6339eb
- 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>
222 lines
12 KiB
Markdown
222 lines
12 KiB
Markdown
# 6. Акселератор
|
||
|
||
## 6.1 Общие сведения
|
||
|
||
Акселератор — внутреннее устройство, реализованное в ППЛМ. Присутствует почти
|
||
во всех конфигурациях Sprinter (Sprinter-2 и выше). Предназначен для ускорения
|
||
пересылки блоков данных между RAM и VRAM (до физического предела скорости ОЗУ).
|
||
Не поддерживает ПЗУ и Fast RAM [accelerator_doc.txt:5].
|
||
|
||
**Возможности:**
|
||
|
||
- Быстрая заливка горизонтальной или вертикальной линии экрана (1..256 пикселей)
|
||
одним цветом; в режиме 640×256 — линия 1..512 пикселей.
|
||
- Быстрое копирование горизонтальной или вертикальной линии (1..256 пикселей).
|
||
- Логические операции AND, OR, XOR с блоками данных.
|
||
|
||
**Внутренняя память:** 256 байт в ППЛМ. Данные загружаются в эту память,
|
||
затем копируются в выбранный участок RAM/VRAM. Операция копирования может
|
||
повторяться многократно — это позволяет заполнять экран текстурой без
|
||
перезагрузки данных.
|
||
|
||
**Автоматический инкремент адреса:**
|
||
|
||
- **Горизонтальные** операции (`LD L,L` — копирование, `LD C,C` — заливка):
|
||
акселератор автоматически инкрементирует регистр HL (адрес приёмника) на
|
||
каждом шаге. Для копирования источник (DE) также инкрементируется.
|
||
- **Вертикальные** операции (`LD A,A` — копирование, `LD E,E` — заливка):
|
||
акселератор автоматически меняет порт `RGADR` (`#89`) — координату Y.
|
||
После завершения операции `RGADR` содержит новое значение
|
||
(Y + размер_блока, если не было переполнения).
|
||
- **Комбинированный** режим (горизонтальный источник + вертикальный приёмник):
|
||
сначала загружается байт из последовательных данных, затем выполняется
|
||
вертикальная запись. `RGADR` инкрементируется; регистр-источник (DE)
|
||
тоже инкрементируется — можно последовательно читать спрайт и рисовать
|
||
его вертикальными строками (§6.3, пример «Спрайт»).
|
||
|
||
## 6.2 Команды
|
||
|
||
Акселератор управляется специальными инструкциями Z80, которые выполняются
|
||
как NOP обычным процессором, но распознаются ППЛМ [IvanMak.txt:810–848].
|
||
|
||
| Инструкция | Код | Действие |
|
||
|-----------|:---:|----------|
|
||
| `LD B,B` | `#40` | **Выключить** акселератор |
|
||
| `LD D,D` | `#52` | **Включить** + режим «задать размер блока» |
|
||
| `LD A,size` | `#3E size` | Установить размер блока (сразу после `LD D,D`) |
|
||
| `LD C,C` | `#4F` | **Горизонтальная заливка** одним байтом |
|
||
| `LD E,E` | `#5B` | **Вертикальная заливка** одним байтом |
|
||
| `LD L,L` | `#6D` | **Горизонтальное копирование** блока |
|
||
| `LD A,A` | `#7F` | **Вертикальное копирование** блока |
|
||
| `LD H,H` | `#64` | Зарезервировано |
|
||
|
||
**Логические операции** (AND, OR, XOR) выполняются командами
|
||
`AND (HL)`, `OR (HL)`, `XOR (HL)` после загрузки блока в память акселератора.
|
||
|
||
## 6.3 Примеры
|
||
|
||
### Копирование экрана (страница 0 → страница 1)
|
||
|
||
```asm
|
||
; страница VRAM уже открыта по адресу #C000
|
||
LD HL, #C000 ; адрес начала линии первого экрана
|
||
LD DE, #C140 ; адрес начала линии второго экрана
|
||
LD BC, #140 ; длина строки по горизонтали (320)
|
||
DI ; запретить прерывания
|
||
LD D,D ; включить акселератор: режим размера блока
|
||
LD A, 0 ; размер блока = 256 байт (0 = 256)
|
||
LD A,A ; вертикальное копирование
|
||
LDIR ; копировать
|
||
LD B,B ; выключить акселератор
|
||
EI ; разрешить прерывания
|
||
```
|
||
|
||
Время исполнения: ~1.2 прерывания (~24–26 мс на полный экран)
|
||
[IvanMak.txt:822–823], [accelerator_doc.txt:37].
|
||
|
||
### Заливка блока одним цветом
|
||
|
||
```asm
|
||
LD DE, #C000 + X ; X — смещение по горизонтали
|
||
LD A, Y
|
||
OUT (#89), A ; RGADR = Y
|
||
DI
|
||
LD D,D ; режим размера блока
|
||
LD A, width ; ширина блока
|
||
LD B,B ; стоп
|
||
LD A, colour ; цвет заливки
|
||
LD C,C ; горизонтальная заливка
|
||
LD (DE), A ; залить
|
||
LD B,B ; стоп
|
||
EI
|
||
```
|
||
|
||
### XOR блока данных
|
||
|
||
```asm
|
||
LD HL, addr_1
|
||
LD DE, xor_data
|
||
DI
|
||
LD D,D
|
||
LD A, 0 ; 256 байт
|
||
LD L,L ; горизонтальное копирование
|
||
LD A, (DE) ; загрузить блок в память акселератора
|
||
XOR (HL) ; XOR с данными в RAM
|
||
LD (HL), A ; сохранить результат
|
||
LD B,B ; стоп
|
||
EI
|
||
```
|
||
|
||
### Копирование вертикальной линии с разделением load/write
|
||
|
||
Загрузка байта в буфер акселератора и запись из буфера в VRAM разнесены —
|
||
между ними можно выполнять произвольный код (например, сменить Y).
|
||
|
||
Буфер акселератора и размер блока **сохраняются** между включениями и
|
||
выключениями (`LD B,B`), что позволяет гибко разделять чтение
|
||
и запись.
|
||
|
||
```asm
|
||
LD HL, #C000 + X1 ; источник
|
||
LD DE, #C000 + X2 ; приёмник
|
||
|
||
DI
|
||
LD D,D ; акселератор вкл, режим размера
|
||
LD A, size ; размер блока
|
||
LD B,B ; выключить (размер запомнен)
|
||
|
||
LD A, Y1
|
||
OUT (#89), A ; RGADR = Y1
|
||
|
||
LD A,A ; вертикальное копирование
|
||
LD A, (HL) ; загрузить байт из (HL) в буфер акселератора
|
||
LD B,B ; выключить (буфер запомнен)
|
||
|
||
LD A, Y2
|
||
OUT (#89), A ; RGADR = Y2 (смена Y между load и write)
|
||
|
||
LD A,A ; вертикальное копирование
|
||
LD (DE), A ; записать буфер в (DE) — акселератор пишет
|
||
; вертикальную линию size пикселей
|
||
LD B,B ; выключить
|
||
EI
|
||
```
|
||
|
||
### Спрайт вертикальными строками из последовательных данных
|
||
|
||
Спрайт хранится как последовательность байт вертикальных линий. Для каждой
|
||
колонки спрайта: загружается байт из последовательных данных, затем
|
||
акселератор пишет его вертикально (автоинкремент `RGADR`). После завершения
|
||
колонки — сдвиг по X (`INC HL`) и повтор.
|
||
|
||
```asm
|
||
LD DE, sprite_data ; DE → последовательные данные спрайта
|
||
LD HL, #C000 + X_COORD ; HL → начальная позиция на экране
|
||
LD B, sprite_width ; ширина спрайта в колонках
|
||
|
||
LD D,D ; акселератор вкл, режим размера
|
||
LD A, sprite_height ; высота одной вертикальной линии
|
||
LD B,B ; акселератор выключили (размер акселератор запомнил)
|
||
|
||
row:
|
||
LD A, Y_COORD
|
||
OUT (#89), A ; RGADR = стартовая Y
|
||
DI
|
||
LD L,L ; режим «загрузить из последовательных данных»
|
||
LD A, (DE) ; загрузить байт спрайта в буфер акселератора
|
||
LD A,A ; вертикальное копирование
|
||
LD (HL), A ; записать — акселератор копирует байт
|
||
; вертикально, RGADR++ на каждом шаге
|
||
LD B,B ; выключить акселератор
|
||
EI
|
||
INC HL ; следующая колонка по X
|
||
DJNZ row
|
||
```
|
||
|
||
## 6.4 Скорость
|
||
|
||
Время работы акселератора ограничено только физической скоростью ОЗУ
|
||
[IvanMak.txt:840–843]:
|
||
|
||
```
|
||
Время ≈ время команды без акселератора + число_байт / 7 000 000 (сек)
|
||
```
|
||
|
||
## 6.5 Комбинированный режим: общая схема
|
||
|
||
Общий паттерн для работы с акселератором в комбинированном режиме
|
||
(горизонтальный источник + вертикальный приёмник):
|
||
|
||
```
|
||
LD D,D ; 1. Включить акселератор, режим размера
|
||
LD A, size ; 2. Задать размер блока (1..256)
|
||
LD L,L ; 3. Режим «горизонтальный источник»
|
||
<чтение байта> ; 4. Загрузить байт в буфер акселератора (LD A,(DE) и т.п.)
|
||
LD A,A ; 5. Режим «вертикальный приёмник»
|
||
<запись байта> ; 6. Записать — акселератор делает вертикальное копирование
|
||
; с автоинкрементом RGADR и приёмника
|
||
LD B,B ; 7. Выключить акселератор
|
||
```
|
||
|
||
После шага 6 `RGADR` содержит Y + size, HL — X + 1 (если был `INC HL`).
|
||
|
||
## 6.6 Прерывания
|
||
|
||
**Старая прошивка:** DI обязателен на время работы акселератора — система
|
||
команд Z80 сильно меняется, и ISR не сможет корректно выполниться
|
||
[IvanMak.txt:844–846].
|
||
|
||
**Новая прошивка:** акселератор может работать с EI. По приходу прерывания
|
||
он отключается, а по `RETI` включается обратно [IvanMak.txt:846–848].
|
||
Использовать этот режим следует с осторожностью — без проверки на реальном
|
||
железе неизвестно, какая версия прошивки установлена.
|
||
|
||
---
|
||
|
||
## 6.7 Кросс-ссылки
|
||
|
||
- Баги акселератора: `12-bugs.md`
|
||
- Использование акселератора в libbgi: `sprite-api-design.md`
|
||
- Ограничение скорости: `accel-fill-budget.md`
|
||
- Fast RAM и конфликт с портом CBL: `04-memory.md §4.6`
|