Данная статья написана в 2003 году для газеты «Абзац» и была опубликована в 16 номере. Это моя первая статья на тему расширенного экрана компьютера «Profi».
Когда я начинал работать с CP/M, то оказался перед проблемой отсутствия, каких либо конкретных данных по этой системе, и, в частности, по расширенному экрану. Затем ситуация изменилась в лучшую сторону, но экран Профи так и остался черным пятном: почти все пришлось узнавать экспериментальным путем. Возможно, кто-то столкнулся с такой же проблемой. Вот с этими людьми мне и хотелось бы поделиться своими наработками.
Расширенный экран «Профи» имеет размер 512*240(h) пикселей, и занимает 32Кб (16Кб информация о пикселях и 16Кб цвета). Можно сказать это два независимых экрана с одинаковым строением, только в одном хранится пиксельная информация (страница 6), а в другом о цвете (страница 3A). Поэтому сейчас я остановлюсь только на обработке пиксельной информации (так сказать, черно-белого экрана). С остальным, думаю, несложно будет разобраться самостоятельно.
Карта памяти CP/M в корне отличается от привычной Спектрумовской. В ней нет ПЗУ, а система занимает верхние адреса. Очень важно иметь четкое представление о строении нижних 64Кб, в дальнейшем это поможет грамотно организовывать работу программы. Как выглядит карта памяти, можно посмотреть на рисунке 1.
![](https://habrastorage.org/getpro/habr/upload_files/0d3/fa6/308/0d3fa63082289ab7cba9ac3abe37d0f1.gif)
Где:
BIOS - соглашения базовой системы ввода/вывода. На этих соглашениях базируется работа BDOS.
BDOS - базовые функции дисковой операционной системы.
Область дополнительных команд - сюда могут загружаться дополнительные системные программы: отладчик, интерпретаторы командных языков и т.п.
Область транзитных программ - именно сюда интерпретатор команд загружает прикладные программы для исполнения.
Базовая страница памяти - включает в себя несколько сегментов кодов и данных, обеспечивающих вход в BDOS и содержащих некоторые системные параметры.
Как видно из рисунка, экран открывается между двумя окнами на место второй страницы. В каждое окно может быть открыта любая страница памяти (в том числе 6 и 3А). Важной особенностью CP/M является то, что у запускаемых файлов нет стартового адреса, все они загружаются и начинают исполняться сразу за базовой страницей, с адреса #100. Это также следует учитывать.
Какое же строение имеет расширенный экран? По вертикали он идентичен экрану Спектрума, только не 192, а 240 пикселей в высоту. И тут для него справедливо все написанное для стандартного экрана.
Основное его отличие - по горизонтали. Следует отметить, что экран представлен не единым «куском», а как бы разрезанным на две части. Это можно сравнить с наличием двух, вытянутых по вертикали, стандартных экранов, расположенных в памяти друг за другом и выводимых одновременно. Первый экран начинается с адреса #A000, второй с адреса #8000. Работа с ними, по отдельности, ничем не отличается от работы со стандартным экраном. Все бы ничего, да только на мониторе они чередуются в линии: байт с первого, байт со второго, с первого, со второго... Расширенный экран получатся разделеным на колонки шириной в одно знакоместо. И попытка работать только с одной частью, приведет к тому, что изображение будет разрезано на вертикальные полоски. Чтобы было понятнее, приведу карты расширенного экрана по знакоместам и по пиксельным линиям.
Карта расширенного экрана по знакоместам выглядит так, как это изображено на рисунке 2.
![](https://habrastorage.org/getpro/habr/upload_files/1ea/91b/da9/1ea91bda9ae7ce5b8392888fcbfcf22d.gif)
Дальше столбцы продолжают чередоваться. Попиксельная карта расширенного экрана имеет вид изображенный на рисунке 3.
![](https://habrastorage.org/getpro/habr/upload_files/318/403/a75/318403a752341dad656f2a890eab4c95.gif)
Как видите, структура расширенного экрана не очень сложная, проблемы возникают только при горизонтальном переходе, здесь уже командой INC L не обойтись. Как же осуществить необходимый переход? Для решения этой проблемы посмотрим на начальные адреса двух половинок экрана в двоичной форме:
Первое знакоместо #A000 = 10100000 00000000
Второе знакоместо #8000 = 10000000 00000000
Третье знакоместо #A001 = 10100000 00000001
Видно, что для перехода из первого знакоместа во второе достаточно выключить 5-тый бит в старшем регистре. Для перехода в третье знакоместо потребуется не только включить 5-тый бит, но и выполнить команду INC L. Так как включение бита вернет нас только в другую половинку расширенного экрана, причем на первое знакоместо. Тут как раз вступает в игру чередование половинок, что и позволяет совершить переход на третье знакоместо. Для примера приведу процедуру расчета адреса знакоместа справа от текущего.
RIGHT: PUSH AF
BIT 5,H
JR NZ,RIGHT1
INC L
SET 5,H
POP AF
RET
RIGHT1: RES 5,H
POP AF
RET
На входе в нее в регистровой паре HL находится адрес текущего знакоместа, на выходе в HL адрес знакоместа справа.
Теперь мы знаем все о строении расширенного экрана, но как его включить? Ведь обычно на месте экрана находится вторая страница. Это можно сделать прямым обращением к портам. Но в CP/M, по возможности, следует избегать подобного решения. Внутри системы почти все уже предусмотрено заранее. Это касается не только расширенного экрана. Обращение к BIOS’у позволит избежать конфликтов между разными версиями CP/M и при использовании периферийных устройств, осуществлять работу с ними через драйвера. Вот две небольшие процедуры для включения и отключения экрана, использующих BIOS в своей работе:
; Включение экрана
SCRON: LD DE,1AFFH
CALL 0F82DH
RET
; Выключение экрана
SCROFF: LD DE,09B8H
CALL 0F82DH
RET
После включения экран занимает адреса с #8000 по #C000, замещая находящуюся там информацию. О чем не следует забывать и не размещать в данной области нужных в этом случае процедур и данных. А это, согласитесь, не совсем удобно, особенно если программа не использует расширенную память.
При необходимости можно пожертвовав скоростью, использовать возможности драйвера дисплея DSPK.DRV (разумеется, он должен быть загружен).
У него имеется обширный набор команд, применение которых позволит без проблем работать не только с пиксельной информацией, но и с цветом. Более подробно узнать о них можно из «Руководства пользователя драйвера дисплея DSPK.DRV», сейчас же я остановлюсь только на одной из его команд. Вот выдержка из руководства:
ESC+i Нарисовать пиктограмку. Сама пиктограмма описывается с адреса 80H:
ORG 80H
DB позиция, строка верхнего левого угла;
DB длина, ширина пиктограммы в знакоместах;
DW указатель на битовую карту точек;
DW указатель на битовую карту палитр.
; При вызове параметры портятся. Структура карт: знакоместа описываются последовательно
; слева направо, строки - сверху вниз.
; Описание одного знакоместа в битовой карте - 8 байт, по байту на строку растра,
; аналогично и в карте палитры.
LD HL,ICON ; желтая стрелка на красном поле
LD DE,80H
LD BC,8
LDIR
.OUTCHAR ESC
.OUTCHAR «i»
ICON:
DB 3,7 - позиция (7,3)
DB 2,1 - размеры 1х2
DW POINTS
DW PALLETS
POINTS:
DB 0,0,0,0FH,0FH,0,0,0
DB 0,40H,60H,0F0H
DB 0F0H,60H,40H,0
PALLETS:
REPT 16
DB 8*red*yellow
ENDM
Как видите, все достаточно элементарно. Данные примеры рассчитаны на использование ассемблера М80+, поэтому в них приведены специфические для него конструкции.
.OUTCHAR - это макрос который определен в файле DEVICE.H.
REPT X - все что находится между этими командами
(в данном случае yyyyy) будет повторено X раз.
yyyyy
ENDM
Ниже я приведу упрощенный вариант .OUTCHAR, который вы можете использовать в простых программах. В больших проектах лучше работать с DEVICE.H и другими подобными файлами, это избавит, в дальнейшем, от многих проблем.
.OUTCHAR MACRO CHR
IF CHR
LD C,CHR
ENDIF
LD D,02
CALL 0FB06H
ENDM
Следует помнить, что макрос должен быть объявлен до его использования. В работе вам могут понадобиться некоторые стандартные константы:
black EQU 0
blue EQU 1
red EQU 2
magenta EQU 3
green EQU 4
cyan EQU 5
yellow EQU 6
white EQU 7
ESC EQU 1BH
Вот пожалуй и все, что я хотел рассказать. Тема далеко не исчерпана, но этого достаточно для начальной самостоятельной работы. Если она кого-то заинтересовала, или у вас есть другие вопросы по поводу CP/M, пишите по адресу: tae1980@yandex.ru