Полное руководство по аппаратному мультиколору.
Совместимость, алгоритмы, эффекты и градиенты
Начало здесь, вторая часть здесь.
Философия мультиколора
Теперь стоит поговорить о некоторых (не)очевидных вещах. Расширенные атрибуты имеют тот же размер — 6144 байта, что и область данных изображения. Причём что наиболее важно — они имеют точно такую же нелинейную структуру. Мне приходилось слышать следующие (неверные) выводы из этого факта:
- Нет смысла писать программы для аппаратного мультиколора, т. к. они будут показывать на обычном Спектруме чёрный экран;
- Надо изменять в 2 раза больше данных, а графических акселераторов не завезли;
- Писать эффекты с расширенными атрибутами сложно.
Чёрный экран
Не встречал настолько злых авторов, которые зануляли бы область атрибутов. Гипотетически такое возможно, и тогда пользователь Спектрума действительно сидел бы перед чёрным экраном, из-за которого (может быть) доносились бы какие-то звуки деятельности программы. Однако типично атрибуты заполняются байтом 04 (зелёный) или 07 (белый), что при отсутствии режима Hi-Color даёт монохромное изображение.
На Спектруме огромное количество программ с монохромной графикой, поэтому спектрумисты могут по крайней мере сложить представление о том, что делает эта программа, хотя и без цвета. Это даёт явное преимущество перед программами, написанными для видеорежимов разнообразных FPGA-эмуляторов.
Надо заметить, что расширенные атрибуты удобно использовать наравне с данными изображения, поэтому какие-то элементы в монохромном режиме могут быть не видны. Например, в игре Hi-Color Hero выстрелы звездолёта сделаны через расширенные атрибуты — это быстро и удобно (красим 8 пикселей одним байтом), но такое решение оставляет игрока на оригинальном Спектруме с «пиу-пиу» без визуализации выстрелов.
Отсюда следует, что разработчик, использующий расширенные атрибуты, должен помнить о Спектрумах без такого режима. Природа атрибутов позволяет использовать для подобной заботы т. н. «скрытые пиксели». Именно так выводится заставка игры Hi-Color Hero+: в нижней строчке изображения есть надпись «МУЛЬТИКОЛОР НЕ НАЙДЕН», закрашенная расширенными атрибутами, но видимая на нерасширенном Спектруме.

Вывод графики
Разработчики на Спектруме работают с монохромной графикой, а 768 байт атрибутов эту монохромную графику просто раскрашивают. С расширенными атрибутами ровно такая же ситуация, поэтому для разработчика фактически ничего (кроме более высокого цветового разрешения) не меняется, но есть нюанс.
Если разработчик выводит статическую картинку в стандартном режиме, то он может сначала занулить область атрибутов (#5800), затем заполнить область изображения (#4000) и, наконец, скопировать реальные атрибуты. Это даёт «моментальное» появление картинки на экране. Но если графика динамическая, то алгоритм меняется: сначала заполняется область атрибутов, а затем «под ней» выводится графика в область изображения.
Возьмём эффект «шторки» (англ. blind), в котором полноэкранная картинка отрисовывается по линиям сверху вниз. В стандартном режиме можно сначала заполнить атрибуты, а затем в цикле (с задержкой) копировать на экран 192 линии изображения сверху вниз (рассчитывая адреса нижеследующих строк). Важным является отсутствие атрибутов, в которых фон (бумага) отличался бы от фона экрана (обычно чёрного). Иначе пользователь будет видеть атрибутные квадраты до тех пор, пока линии картинки не дорисуются до них.
Расширенные атрибуты имеют высоту ряда в 1 пиксель. Это делает вывод данных изображения взаимозаменяемым с выводом атрибутов. Можно сначала занулить расширенные атрибуты (#6000), затем заполнить данные изображения (#4000), а затем копировать 192 линии расширенных атрибутов сверху вниз (рассчитывая адреса нижеследующих строк). Фон в копируемых атрибутах при этом может не совпадать с фоном экрана. В стандартном режиме так не делается, потому что изображение в этом случае появлялось бы по знакоместам 8×8, что некрасиво.
Вопрос вывода графики сводится к решению задачи «что выводить первым»: изображение или (расширенные) атрибуты? Вопроса вывода 12288 байт (изображение + расширенные атрибуты) вместо 6144 байт изображения обычно не стоит. Если же необходимость возникла, то надо понимать, что байты расширенных атрибутов имеют те же смещения от начала их области, что и байты изображения, а значит, рассчитывать эти смещения надо по-прежнему один раз. Не надо писать отдельные процедуры для расчёта адресов в области атрибутов и в области изображения.
Разработчик имеет два подхода: 1) использование процедурных библиотек, в т. ч. процедур ПЗУ, для визуализации графики и печати текстов без изменений (с заполнением расширенных атрибутов) и 2) переписывание вывода байтов изображения на вывод байтов расширенных атрибутов в существующих эффектах.
Адаптация эффектов
В любом случае, ему не приходится иметь дело с terra incognita, изобретать велосипеды и судорожно искать примеры кода от тех, кто уже «раскурил» этот «новый» видеорежим. Ничего нового в нём нет, всё хорошо известно, а существующие базы статей на ZXPress и ZXDN точно так же применимы к режиму Hi-Color, как и к стандартному режиму.
В стандартном режиме цветные шрифты могут быть выведены либо печатью шрифтов 8×8 «между знакоместами», либо их увеличением по высоте. Для печати текста в режиме Hi-Color можно использовать стандартный вызов RST #10 с заранее подготовленными расширенными атрибутами. Это можно делать даже из Бейсика, как демонстрирует программа ColorPRINT (в версии для Hi-Color):
Раскраска каждого знакоместа описывается 8 байтами атрибутов, называемыми мультиколорным градиентом (для краткости — просто градиентом). Одни градиенты больше подходят для раскраски заголовков, другие — для текста, третьи — для подписей. Чтобы читатели не ломали над этим голову, поделюсь своей коллекцией:
BASE: db #04, #05, #45, #07, #47, #45, #04, #05 ; базовый градиент (голубой-белый-зелёный)
TEST: db #FF, #07, #47, #07, #47, #47, #07, #FF ; белые полоски на границах знакомест
RBW0: db #02, #42, #46, #44, #04, #05, #01, #03 ; радуга (Color PRN)
RBW1: db #41, #03, #02, #42, #46, #44, #04, #05 ; сдвинутая радуга
RBW1_I: db #05, #04, #44, #46, #42, #02, #03, #41 ; перевёрнутая радуга
YLBL: db #46, #06, #47, #07, #45, #05, #41, #01 ; градиент жёлтый - синий (Color PRN)
BLRD: db #01, #05, #45, #07, #47, #46, #42, #02 ; градиент синий - красный (Color PRN)
YLBL2: db #06, #46, #47, #07, #45, #05, #41, #01 ; градиент жёлтый - синий
WHCY_P: db #07, #47, #07, #47, #45, #05, #45, #05 ; серху - белый, снизу - голубой (заголовок)
WHGR_P: db #07, #47, #07, #47, #44, #04, #44, #04 ; серху - белый, снизу - зелёный (подпись)
YLGR_P: db #06, #46, #06, #46, #44, #04, #44, #04 ; сверху - жёлтый, снизу - зелёный (текст, основа)
MGRD_P: db #03, #43, #03, #43, #42, #02, #42, #02 ; сверху - фиолетовый, снизу - красный (текст, выделение)
Заполнить весь экран одним из градиентов можно следующим тривиальным кодом:
; screen-fill.asm
ORG #C000
ld hl,MGRD_P ; таблица градиента 8 байт
ld (SGRAD), hl
call SCRATTR
ret
SCRATTR:
ld hl, #6000 ; начальный адрес расширенных атрибутов
ld c, 3 ; 3 прохода
MNF:
push bc
ld b, 8 ; 8 рядов
ld ix,(SGRAD) ; восстанавливаем указатель на градиент
CLRF:
push bc
ld a, (ix) ; текущий цвет
inc ix
ld d, h
ld e, l
inc de
ld (hl), a
ld bc, 256
ldir
pop bc
djnz CLRF
pop bc
dec c
jr nz, MNF
ret
SGRAD: dw 0
BASE: db #04, #05, #45, #07, #47, #45, #04, #05 ; базовый градиент (голубой-белый-зелёный)
Шрифты, раскрашенные по вертикали, выглядят очень выигрышно, но ещё лучше смотрится анимация расширенных атрибутов. Пробегающую по буквам полосу хорошо использовать, например, для того чтобы обратить внимание пользователя на очередное достижение или обновившиеся очки в игре, логотип группы, ник автора в демо и т. д.![]() |
![]() |
![]() |
CTAB: db X, Y ; координаты начала заполнения в знакоместах
dw GRAD ; указатель на градиент
db N ; ширина заполняемой полосы в знакоместах
db #FF ; признак конца таблицы
Например, для градиентной анимации можно создать такую таблицу:
CTAB: db 5,11 ; первый градиент
dw GRAD1
db 10
db 5,11 ; второй градиент
dw GRAD2
db 10
db 5,11 ; третий градиент
dw GRAD3
db 10
. . .
db #FF
Достоинство подобных структур в том, что их легко обрабатывать и они хорошо компрессируются (на случай, если кто-нибудь решит создать на этой базе целый мультфильм или demo). У тех, кто осилил дочитать до этого места, должно было сложиться полное понимание того, как писать крутые программы, показывающие себя не только в стандартном режиме, но ещё больше раскрывающиеся в режиме Hi-Color.Более глубоким подходом является замена вывода данных изображения на вывод расширенных атрибутов: здесь нам потребуется менять адреса. При этом большинство эффектов также могут быть адаптированы «в лоб». В качестве примера приведу адаптацию упоминавшегося выше эффекта шторки из журнала ZX-Ревю №1–2 за 1997 год. Мне потребовалось изменить 3,5 строчки (не считая инициализации).
Продолжение следует
; screen-blind.asm
SCRSHOW:
ld hl, SCRWARN ; заполнение атрибутной картинкой
ld de, #5800 ; для тех бедных спектрумистов
ld bc, 768 ; у которых почему-то нет Hi-Color
ldir
ld hl, SCREEN ; переброска данных изображения
ld de, #4000
ld bc, #1800
ldir
ld hl, #6000 ; зануление расширенных атрибутов
ld de, #6001
ld (hl), 00 ; чёрное на чёрном
ld bc, 6143
ldir
; раскраска расширенных атрибутов
ld hl, SCREEN+6144 ; начало расширенных атрибутов
ld de, #6000 ; было #4000
or a
sbc hl, de
ld b, h
ld c, l ; BC = смещение
ld a, 191 ; Y-координата (0..191)
SMLP: push af, bc
ld c, 0 ; X-координата (0..255)
call 8880 ; HL = адрес в видеопамяти
ld bc, #2000
add hl, bc ; добавляем #2000 к выхлопу 8080
pop bc, af
push bc
ld d, h
ld e, l ; DE = экран
add hl, bc ; HL = буфер + смещение
ld bc, 32
ldir ; копируем строку
halt
pop bc
dec a
cp 255
jr nz, SMLP
ret
SCREEN: INCBIN “images/multicolour.scr” ; 12288 байт
SCRWARN: INCBIN “images/attr_warning.bin” ; 768 байт


