- 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>
12 KiB
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)
; страница 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].
Заливка блока одним цветом
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 блока данных
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), что позволяет гибко разделять чтение
и запись.
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) и повтор.
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