# 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`