Продолжение статьи по работе с расширенным экраном компьютера "Profi" опубликованной в 2003 году 16 номере в газете "Абзац". Информация значительно переработана и дополнена, в том числе примерами программирования.
Статья была опубликована в 2019 году в 25 номере журнала по ZX Spectrum'у "ЗаRulem Печатное Слово".
Статья написана в соавторстве с Вадимом Чертковым.
В 2003 году в №16 номере газеты «Абзац» вышла моя статья «Расширенный экран «Profi», что это такое и как с ним работать». С тех прошло уже 16 лет… За это время я (TAE) успел уйти со Спектрума и вернуться. Старая информация была переосмыслена, получена новая. Сейчас же хочу попробовать представить некий итог этого процесса, так сказать подвести черту, перед тем как двигаться дальше. И мне кажется, начать следует с самого начала.
Компьютер «Profi» представляет собой развитие компьютера ZX Spectrum 128. Разработчики «Profi» стремились минимальными изменениями и средствами расширить возможности Спектрума, что наложило отпечаток на принимаемые решения, в том числе на реализацию расширенного экрана. Максимальный эффект от всех изменений можно получить в операционной системе CP/M, так как именно в ней разработчики видели основное направление развития своего детища. Но и в режиме «стандартного Спектрума» все дополнения доступны без особых проблем. Я же буду описывать материал, и приводить примеры применительно именно к ОС CP/M.
Для того, что бы было возможным запустить ОС CP/M или ей подобную, необходимо иметь ОЗУ в нижней части адресного пространства (с адреса 0000h до адреса XX00h, далее в принципе может идти и ПЗУ, но возможен вариант, когда ПЗУ при работе системы отключается и все 64К представляет собой ОЗУ). Поэтому разработчики «Profi» добавили возможность отключения ПЗУ в адресах 0000h..3FFFh, на его место включается страница 0. Что позволяет запускать систему CP/M или использовать для программ больший объём памяти в режиме спектрума. Часть памяти занимают части ОС CP/M. Общая карта памяти представлена на рисунке 1.

Где:
-
BIOS - Базовая система ввода/вывода. BDOS работает с внешними устройствами вызывая функции BIOS;
-
BDOS - базовые функции дисковой операционной системы.
-
Область транзитных программ - именно сюда интерпретатор команд загружает прикладные программы для исполнения;
-
Базовая страница памяти - включает в себя несколько сегментов кодов и данных, обеспечивающих точку входа в BDOS, точку входа в BIOS и содержащих некоторые системные параметры.
Расширенный экран «Profi» имеет размер 512*240 пикселей и занимает 30Кб (15Кб информация о пикселях и 15Кб цвета). Цвет задаётся для каждого байта пикселей, то есть каждые 8 точек могут иметь два цвета (Ink и Paper). Что в восемь раз увеличивает вертикальную «цветность», относительно стандартного экрана Спектрума. Но информация о цвете теперь занимает значительно больше места.
За всё время существовали версии компьютера «Profi» с черно-белым экраном (цвет не реализован), цветные в двух вариантах: 8 цветов с 2 двумя градациями яркости и 16 цветные машины, а так же с расширенной палитрой 16 из 256 цветов. Работа с экраном у цветных машин и с расширенной палитрой идентична. О самой палитре рассказу чуть ниже, а сейчас остановимся на базовых принципах организации работы.
Как и в ZX Spectrum 128 у компьютера «Profi», два равнозначных расширенных экрана с возможностью единовременного отображения только одного из них. Экраны занимают по две страницы (таблица 1), одна страница хранит пиксели, другая байты атрибутов.
Структуры хранения графики и цвета идентичны, обе части представляют собой копии друг друга, только хранят информацию о разных составляющих изображения.

Можно выделить две схемы работы с расширенным экраном:
-
В один момент времени доступна или страница пикселей или страница атрибутов. Сначала подключаем одну страницу, делаем запись, потом подключаем другую страницу и так же делаем запись.
-
Для 1-го экрана (только для него) доступен способ, когда страница пикселей (06h) может быть подключена с адреса #8000, а страница с атрибутами (3Ah) в окне проецирования (с 4000h или с C000h). Таким образом, получается одновременный доступ ко всему экрану.
Из-за возможности получить одновременный доступ к графике и цвету 1-ого экрана он используется по умолчанию в ОС CP/M. Так сказать, он является основным, а 0-ой экран дополнительным.
Небольшое отступление. Конструктивно в компьютере «Profi» имеется всего одно окно проецирования страниц, но само окно может размещаться в 2х местах, таким образом, получаем две модели размещения страниц:
-
Окно с адреса #C000 - режим адресации ZX-Spectrum 128
-
Окно с адреса #4000 - режим адресации CP/M.
Более подробно о работе с расширенной памятью рассмотрим далее.
Экранная область расширенного видеорежима (512x240) устроена подобно экранной области стандартного видеорежима ZX-Spectrum. Т.е. состоит из области пикселей и области атрибутов, но имеется два отличия:
Первое - байт атрибутов задаёт цвет области из 8-и пикселей, а не 64-х как в ZX-Spectrum. Каждый байт пикселей имеет свой собственный байт атрибутов, это так называемый аппаратный мультиколор.
Второе - область пикселей и соответствующая ей область атрибутов располагаются в памяти не линейно, а разделяется на 2 полуэкрана по 32 столбца в каждом. Каждый полуэкран имеет структуру экранной области ZX-Spectrum, за исключением того, что он состоит не из трёх третей, а из четырёх четвертей, но последняя четверть неполная и состоит из 48 линий (6 строк по 8 линий).
Полуэкраны выводятся с чередованием, т.е. один полуэкран это нечетные столбцы, а второй - чётные.
При отображении пиксельной строки сначала выводится байт из одного полуэкрана, потом из второго, затем следующий байт из первого. Если условно разделить страницу пикселей на 2 равные части, то первая часть хранит нечётные столбы, а вторая - чётные.

Точно таким же образом устроена и область атрибутов. Адрес в экранной области можно представить вот такой схемой:

Если в такую экранную область выводить текстовую информацию с размером символа 8x8 точек (8 линий по байту), то разрешение экрана составит 64x30 символа.
Что бы было понятнее, приведу карту расширенного экрана по знакоместам (таблица 2). При открытии графики с адреса #8000 строение экрана она выглядит так:

Дальше столбцы продолжают чередоваться. Пиксельная карта расширенного экрана имеет такой вид (таблица 3).

Как видите, структура расширенного экрана не очень сложная, проблемы возникают только при горизонтальном переходе, здесь уже командой INC E не обойтись (здесь и далее считаем, что адрес на экране находиться в регистровой паре DE). Как же осуществить необходимый переход? Для решения этой проблемы посмотрим на начальные адреса двух половинок экрана в двоичной форме:
Первое знакоместо #A000 = 10100000 00000000
Второе знакоместо #8000 = 10000000 00000000
Третье знакоместо #A001 = 10100000 00000001
Видно, что для перехода из первого знакоместа во второе достаточно выключить 5-тый бит в старшем регистре. Для перехода в третье знакоместо потребуется не только включить 5-тый бит, но и выполнить команду INC E. Так как включение бита вернет нас только в другую половинку расширенного экрана, причем на первое знакоместо. Тут как раз вступает в игру чередование половинок, что и позволяет совершить переход на третье знакоместо. Для примера приведу процедуру расчета адреса знакоместа справа от текущего.

На входе в нее в регистровой паре DE находится адрес текущего знакоместа, на выходе в DE адрес знакоместа справа.
Для уменьшения временных издержек лучше использовать вариант в виде макроса, там нет лишних переходов, и не сохраняются регистры AF. Самым же оптимальным решением будет обработка двух смежных знакомест (на двух полуэкранах) в одной итерации цикла. Тогда для перехода на второе знакоместо будет достаточно написать «RES 5,D», а переходить в третье знакоместо так «SET 5,D; INC E».
Процедура расчёта адреса в экранной области, координаты заданы в регистровой паре DE. Регистр D содержит координату X (0..63), Регистр E содержит координату Y (0.239).
Calc_ADDR:
xor a
srl d ;младш.бит X выдвинули в C
ccf ;инвертировали
rra ;в 7-й бит А
scf ;потом 1
rra ;завинули
scf
rra ;получили 10X????? (экран с C000)
xor e
and 11100111B
xor e
push af
ld a,e
rrca
rrca
rrca
xor d
and 11100000B
xor d
ld e,a
pop af
ld d,a
ret
Непосредственно с графикой мы закончили, переходим к цвету и совместной работе с графикой и цветом.
Как сказано выше, цвет открывается с адреса #4000 и его строение идентично строению графики. То есть все, то, что было сказано на счет графики справедливо и для цвета, только поправкой на смещение адреса.
Если используется 1-й экран с одновременным доступом к графике и цвету, то для пересчета адреса между ними используем такую конструкцию «ld a, 11000000B; xor d, ld d,a».
Если работаем с графикой и цветом последовательно в одном окне, то для перехода между графикой и цветом ни каких расчетов проводить не нужно, просто переключаем странички памяти.
Мы не будем разбирать версии компьютера «Profi» с 8 цветные и двумя градациями яркости. Во-первых, он ни чем не отличаться стандартного экрана ZX Spectrum’а (кроме разрешения), а во-вторых, сильно сомневаюсь, что в настоящее время ещё остались подобные живые машины.
В 16 цветных версиях компьютера «Profi» разработчики отказались от бита мерцания, превратив его во второй бит яркости. Теперь paper и ink имеют свои раздельные биты яркости и можно с полной уверенностью говорить, что «Profi» может отображать 16 цветов (реально 15, так как черный не имеет яркости).

Можно представить, что 16 цветов кодируются четырьмя битами. Младшие части (3 бита) которых находятся там же где и соответствующие биты в атрибуте у ZX-Spectrum, А старшие (ещё один бит) в 6-м и 7-м битах (рис.2). Цифра в квадратике указывает на номер бита в коде цвета, если мы его представляем в виде 4-х битового значения. Буква i – ink, p-paper, Y- интенсивность (яркость). Т.е. цвет (ink или paper) можно мысленно представить в виде 4-х битового значения xxxx (igrb), но надо помнить, что в байте атрибутов оно хранится не так!
А вот теперь переходим к разбору такой интересной вещи как палитра 16 из 256 цветов.
ZX-Spectrum имеет слишком малое количество разных цветов для отображения графики. По сути их всего 8, бит яркости изменяет лишь яркость цвета, но не его цветность, с точки зрения цвета – он не меняется. Цвет изменится только, если изменится соотношение составляющих его компонентов (красный, зеленый и синий). Их процентное отношение. На Спектруме получается, что компонента или есть (бит равен 1 или 100%) или её совсем нет (0%).
Как увеличить кол-во отображаемых цветов, не переделывая экранную область? На первый взгляд кажется - никак, но это неверно. Простейший выход – применение палитры.
Название взято из области изобразительного искусства. Художник рисует картину красками, краски он смешивает в палитре, используя несколько исходных красок с разными цветами, смешивая их в нужной пропорции - получает нужный цвет, но в палитре количество ячеек не безгранично. Художник наполняет их по своему усмотрению и потом, пользуясь ими, рисует картину. Другую картину он может рисовать с другими наборами цветов. В общем, мысль ясна.
Итак. Мы имеем на экране одновременно столько же _разных_ цветов, как и раньше (16), но сам цвет при выводе на монитор более тонко задается. Если ранее (без палитры) мы имели по сути всего 8 комбинаций с уровнем яркости, то сейчас компоненты зеленой и красной компоненты задаются 3-я битами, что дает уже 8 уровней (у Спектрума 2 уровня или есть или нет – один бит), для синей компоненты есть 2 бита, т.е. 4 уровня. В сумме это дает 256 разных комбинаций. Т.е. у «Profi» имеется палитра 16 из 256 цветов. Но в один момент времени можно использовать на экране только 16 цветов, т.к. атрибут имеет 8 бит, 4 из которых задают цвет пикселей установленных в 1, и 4 установленных в 0.
Т.е. то, что ранее называлось цветом (от 0 до 15) теперь является просто индексом, т.е. указателем на реальный цвет. Таким образом, байт атрибутов, вообще говоря, выглядит так (т.е. представляется нам сейчас):

Где, P указывает на поле PAPER, I указывает на поле INK. Цифра рядом с буквой указывает на номер разряда в двоичном значении индекса (индекса «цвета»).
Палитра хранится в статическом ОЗУ которое представляет собой 16 слов по 8 бит, т.е. 16 байт.
Т.е. при отображении видео-области на мониторе берутся значения байта пикселей и байта атрибутов, затем происходит отображение пикселей на мониторе последовательно, начиная со старшего бита к младшему. Если бит равен 1, то берется 4-х битное значение INK из байта атрибута, если он равен 0, то 4-х битное значение PAPER из того же байта атрибута. Это значение является числом от 0 до 15, которое задает адрес в статическом ОЗУ где лежит реальное значение цвета. Видеоконтроллер берет указанное значение реального цвета и именно его и подает на монитор для отображения. Ещё более другими словами, сейчас цвет кодируется при выводе на монитор не 4-я битами, а 8-ю. В памяти, в экранной области, он по-прежнему задается байтом атрибутов. Мы по прежнему будем называть биты в байте атрибута битами яркости, битом красного, синего и зеленого цвета, но вообще, конечно это уже не так, это просто биты. В режиме Спектрума они имеют указанные значения (т.е. программы Спектрума полагают, что задав значение атрибута 01110000 мы получим черный ink и жёлтый paper).

Условно байт состоит из 3-х частей, которые соотв. Цветам Green – зелёный, Red – красный и Blue –синий. Так как синяя компонента представлена всего 2-я битами, то считается, что у нее есть младший бит, но он равен всегда 0. Т.е. если мы задаем значение синей компоненты в 11 (т.е. десятичное 3), то для получения белого цвета зелёная и красная компоненты должны быть заданы в значение 110 (десятичное 6). И байт палитры соответствующий белому цвету будет выглядеть как 11011011.
Значения в ячейках палитры (для краткости просто палитра) по умолчанию, соответствуют ситуации отображения цвета как в предыдущих моделях компьютера без палитры. Это так называемы цвета по умолчанию или стандартные цвета. Палитра ZX-Spectrum имеет вид:

Конечно, в любую ячейку палитры мы можем поместить любое значение байта, перемешать существующие цвета, инвертировать их и т.д.
По сути номера цвета в этой таблице (и вообще в Спектруме) заданы виртуально, это всего лишь комбинации битов. Единственное, что привязывает эти комбинации битов к номерам лишь то, что адресные входы статического ОЗУ палитры подключены так

Задав значение «цвета» в атрибуте равное 0 (цветом мы тут называем комбинацию битов в полях INK или PAPER и прибавив к ним соответствующий бит «яркости»), мы указываем на ячейку 0 палитры, указав значение 110 (6) на ячейку с адресом (номером) 6. А значение с установленными битами яркости и компонент G, R и B указывает на ячейку 15 палитры.
А вообще, при отображении экрана ZX-Spectrum на монитор мы можем раскрасить в группе из 8-и точек любые из них 2-я разными цветами из палитры 8 цветов. (Получается ведь так). Установленные биты байта имеют один цвет (INK), а неустановленные другой (PAPER).
Для программирования палитры используется подпрограммам «SetPal», которая имеет три точки входа:
-
SetPal – установка переделанной палитры. На входе в регистровой паре HL – должен находиться адрес устанавливаемой палитры, или 0 для установки стандартной для Спектрума палитры.
-
SetPal.StPal - установка стандартной палитры. Будет установлена стандартная палитра.
-
SetPal.9 - установка переданной палитры. Вход для продвинутых пользователей. Все предварительные настройки выполнятся в главной программе до вызова подпрограммы.
SetPal:
;Программирование палитры.
;* Точка входа SetPal - установка переданной палитры.
; На входе: hl - адрес новой палитры или 0 для установки стандартной [0].
;* Точка входа SetPal.StPal - установка стандартной палитры.
;* Точка входа SetPal.9 - установка переданной палитры. Все настройки выполнятся до вызова.
; На входе: hl - адрес новой палитры.
;
;Портит: af, hl, de, bc
ld a, h ; if hl=0
or l ;
jr nz, SetPal.P1 ; then
SetPal.StPal: ld hl, Palette.Std ; else <!> Точка входа
SetPal.P1: ei
halt ; В прерывании портятся HL&AF, т.к. стэк стоит на ПЗУ
SetPal.9: di ; <!> Точка входа
ld c, 7Eh
ld d, 16
SetPal.P2: ld a, (hl) ; физический цвет
cpl ; инверсия
ld b, a ; данные в рег. палитры
dec d
ld a, d
out (0FEh), a
out (c), d ; данные из B заносятся в рег.палитры
inc hl
jr nz, SetPal.P2
ret
;----------------------------------------------------------------------
Palette.Std:
DB 0 ; BLACK
DB 00000010B
DB 00010000B
DB 00010010B
DB 10000000B
DB 10000010B
DB 10010000B
DB 10010010B ; WHITE
DB 0 ; gray
DB 00000011B
DB 00011000B
DB 00011011B
DB 11000000B
DB 11000011B
DB 11011000B
DB 11011011B ; WHITE (BRIGHT 1)
К сожалению, не существуют аппаратного метода получения установленной палитры, поэтому следует сохранять копию палитры при установке, что бы к ней можно было вернуться. В ОС PQ-DOS имеются встроенный механизм, берущий на себя всю заботу по организации работы с палитрой, в том числе по сохранении текущей палитры и возврату её по запросу. Поэтому если вы работает в этой ОС, крайне желательно использовать её встроенный инструментарий. Если же вы работает в обычных «старых» версиях ОС CP/M, то следует считать, что по умолчанию установлена стандартная палитра, и не забывать восстанавливать её при выходе из своих программ.
Для включения нужной страницы в окне проецирования настоятельно рекомендуем использовать функцию SECMRS подсистемы Concurrent BIOS, которая сохраняет последние отправленные значения CMRS в системной переменной. CBIOS использует эту переменную при обработке прерываний и по выходу из всех обработчиков восстанавливает CMRS именно по этой переменной. Т.е. если мы не будем пользоваться стандартной функцией, то получим проблемы с подключением страниц. При вызове SETCMRS регистр D содержит значение для CMR0 (7FFD), регистр E значение для CMR1 (DFFD). Никаких манипуляций с битами не происходит, значения сохраняются в памяти и отправляются в указанные регистры. Подробнее о функциях CBIOS можно узнать из его описания, которое имеется на системном диске.
Если у кого остались вопросы он всегда может обратиться по одному из следующих адресов.
-
FidoNet: Tarasow Aleksey 2:5053/57
-
E-mail: tae1980(очень злая собака)yandex.ru
А на форуме, в группе ВК и сайте есть много интересного, а все новое будет выкладываться, в том числе и там.
Приложение 1. Адресация памяти
ОЗУ Профи, как и многих других Спектрум совместимых машин, состоит из страниц по 16К. Максимально адресуется 64 страницы. Адресное пространство состоит из 4х сегментов, но только в один из них можно включать произвольные страницы – это окно проецирования. Окно имеет два положения в адресном пространстве, формируя таки образом две модели памяти ZX-Spectrum и Profi.
Управление памятью осуществляется двумя внешними регистрами - CMR0 и CMR1 (Control Memory Register).
Регистр CMR0 представляет собой системный регистр Spectrum-128 подключенный к порту 7FFDH и работающий только на запись. Его формат приведен на рисунке 6.

Пятый бит этого регистра в режиме CP/M по мысли разработчиков должен включать на доступ регистры палитры, но в действительности регистры палитры доступны и без него.
В режиме Спектрума четвертый бит определяет страницу используемого ПЗУ, в режиме CP/M установка этого бита в 1 совместно с битом 5 CMR1 модифицирует доступ к портам. А именно при ROM14=0 периферия адресуется как в PROFI+ (V3.2), при ROM14=1 и CPM=0 модифицируется доступ к периферии в результате чего становится доступно еще около 30 портов.
Третий бит определяет какая страница экрана в данный момент отображается на мониторе.
Младшие три бита содержат номер текущей страницы (в режиме спектрума), в CP/M они определяют номер страницы в текущем банке памяти.
Регистр CMR1 представляет собой системный регистр Профи и он доступен по адресу DFFDH во всех режимах адресации периферии. Назначение разрядов приведено на рисунке 7.

Рисунок 8.Т.е. всю оперативную память (ОЗУ) можно представить восьмью банками по 8 страниц в каждой (всего страниц 64), как бы расширение памяти Спектрума. Нумерация начинается со страницы 0 до 7, далее используется следующий банк. Все ОЗУ удобно представлять в виде таблицы (см рис. 3) 8x8 ячеек, где каждая ячейка содержит номер страницы. Т.к. общее количество ячеек 64, а объем одной страницы 16К, то максимальный объем доступной памяти равен:
16384 x 64 = 1048576 байт = 1024 Кб = 1Мб.
Номера страниц можно записывать и в восьмеричной системе, первая цифра будет представлять собой номер строки, вторая - колонки.

Физически ОЗУ выполняется в виде 4-х линеек м/с КР565РУ7 или аналогичных. Странички памяти подключаются в окне проецирования. Младшие 3 бита номера страницы содержит рег. CMR0, а старшие 3 бита рег. CMR1. Некоторые страницы могут отсутствовать (если у Вас менее 1мб ОЗУ то это должно быть очевидно), а некоторые могут пересекаться. Например, при использовании м/с ОЗУ КР565РУ5 совместно с 565РУ7 страница 30=34=38=3C, а страница 31=35=39=3D и т.д., т.е. линейка на РУ5 содержит 4 страницы, а линейка РУ7 16.
Банк 0 представляет собой память Спектрума-128. В CP/M назначение страниц следующее:

Остальные страницы считаются свободными.
Карта адресации процессора выглядит следующим образом:
В режиме Спектрума:

В режиме Профи:

Т.е. сегмент 0 всегда содержит нулевую страницу, а сегмент 2, как правило содержит страницу 02 (но имеется возможность подключить страницу 06). Указанное разделение на режимы "Спектрума" и "Профи" осуществляется установкой или сбросом бита 3 CMR1.
Автор: tae1980