2.8. ЭМУЛЯЦИЯ КОМАНД БЕЙСИКА ИЗ МАШИННОГО КОДА
Здесь мы рассмотрим как выполнить БЕЙСИК-овские команды,
связанные с графикой, из машинного кода. Как правило это
несложная задача, поскольку в ПЗУ имеются процедуры, способные
это сделать, надо только знать, каким образом к ним следует
обращаться.
2.8.1 CLS (CLEAR SCREEN)
Сначала займемся очисткой экрана. В машинном коде это
можно сделать вызовом процедуры CLS, расположенной в ПЗУ по
адресу 0D6BH (3435). В результате ее работы выключаются все
пикселы на экране, а цветовые атрибуты устанавливаются такими,
как установлено в системной переменной ATTR_P 5C8DH (23693). Ее
побитовая раскладка стандартна для атрибутов (см. Рис.8, с.16)
Данная процедура работает точно так же, как и соответствующая
команда БЕЙСИКа.
Если хотите, то можете очистить только нижнюю часть экрана
(обычно это две нижние строки). Это делается вызовом процедуры
CLS_LOWER, которая находится по адресу 0D6EH (3438). В отличие
от основного экрана эта область очищается с цветом бордюра, а
не с цветом, установленным в ATTR_P (см. с. 72) .
Среди процедур ПЗУ есть еще одна, обеспечивающая более
мощные возможности. Она называется CL_LINE (0E44H = 3652) и
очищает заданное количество строк в нижней части экрана. Перед
ее вызовом в регистре B должно быть установлено количество
строк, подлежащих очистке от 01 до 18H (от 1 до 24). Так,
например, чтобы очистить 10 нижних строк, нужно предварительно
в регистр B заслать число 0AH.
Эту процедуру можно применять двумя способами. Если нуле-
вой бит системной переменной TVFLAG (5C3C = 23612) выключен, то
при очистке используются цвета экрана, а если он включен, то
используется цвет бордюра. Таким образом, здесь есть возмож-
ность очистить одновременно весь экран, включая и нижние две
строки, в цвета ATTR_P. Процедура CLS сделать такого не может.
В то же время, следует обратить внимание на то, что процедура
CLS после очистки экрана инициализирует курсор и текущая
позиция печати устанавливается в исходное положение - левый
верхний угол. Процедура же CL_LINE этого не делает.
2.8.2 Скроллинг экрана.
Когда Вы пытаетесь напечатать что-либо за последней
возможной позицией печати, то вместо результата получаете
сообщение "scroll?" в нижней части экрана и компьютер ждет от
Вас нажатие клавиши. Если это клавиша "N" или "BREAK", печать
на экране прекращается с сообщением об остановке, в противном
случае печать продолжается. Экран вроде бы заполнен, но печать
возможна, происходит скроллинг вверх. Этот скроллинг происходит
автоматически и длится до тех пор, пока вся информация,
присутствовавшая на экране, когда выходило сообщение "scroll?",
не скроется из виду за верхней кромкой экрана.
Такой вид скроллинга называется автоматическим и он
существует на "Спектруме" как в БЕЙСИКе, так и в машинном
коде.
Но возможен также и "ручной" скроллинг. Вызов процедуры
CL_SC_ALL (0DFEH = 3582) "прокрутит" весь экран, но при этом
возникнут несколько неожиданные эффекты:
- во-первых, позиция печати не изменится и останется там
же, где была. С этим Вам придется разбираться вручную.
- во-вторых, если первая строка нижней части экрана
(системного окна) не пуста или имеет цвет, отличный от цвета
основного экрана, то результат может быть не сосвсем тем, какой
Вы ожидаете.
Другой способ исполнения "ручного" скроллинга еще
интереснее. Он базируется на использовании процедуры CL_SCROLL
(0E00H = 3584). С ее помощью можно "прокручивать" только часть
экрана. Предварительно в регистр B надо занести количество
строк, подлежащих скроллингу (обратите внимание на то, что
изменено будет на одну строку больше). Минимальное количество
строк - 1. В этом случае нижняя строка экрана будет поднята на
одно знакоместо вверх, а снизу появится чистая строка. Для
того, чтобы переработать весь экран, следует установить число
17H. Таким образом, действие этой команды состоит в перемещении
на одну позицию вверх "B" нижних строк и в очистке нижней
строки.
2.8.3. Временная задержка.
БЕЙСИК-оператор PAUSE можно легко эмулировать в машинном
коде. Единицей измерения времени в "Спектруме" являются пяти-
десятые доли секунды (потому, что частота переменного тока в
нашей сети - 50Гц. Если бы Вы жили в Англии, то у Вас в секунду
проходило бы не 50, а 60 прерываний работы процессора, т.к. там
частота сети равна 60 Гц).
Для того, чтобы исполнить паузу на m пятидесятых долей
секунды, Вам достаточно загрузить это число m в регистровую
пару BC, а затем вызвать процедуру ПЗУ PAUSE_1, расположенную
по адресу 1F3DH (7997). Работая, процедура обеспечит заданную
паузу. Во время своей работы процедура регулярно опрашивает
системную переменную FLAGS (5C3BH = 23611). Ее пятый бит, если
он включен, свидетельствует о том, что произошло нажатие
клавиши. Таким образом, пауза может быть прервана нажатием
любой клавиши - все, как в стандартном БЕЙСИКе.
Если Вы зашлете в регистровую пару BC ноль, то установлен-
ная пауза будет неограниченной, то есть до нажатия клавиши.
Вам, может быть, потребуется случай, когда пауза должна
быть выдержана в течение заданного времени и не должна
прерываться нажатием клавиши. Поможет несложная процедура:
78 PAUSE LD A,B ; Проверка BC на
B1 OR C ; ноль.
C8 RET Z ; Выход, если так.
0B DEC BC ; Уменьшение BC.
76 HALT ; Задержка на 1/50
; секунды (точнее - до
; следующего прерыва-
; ния, которое пройдет
; чуть быстрее).
18F9 JR PAUSE ; Возврат для повтора.
Зашлите в BC требуемую величину задержки и вызывайте эту
процедуру.
2.8.4. Изображение точек.
Для изображения точек на экране из машинного кода есть два
приема. Первый, и наиболее простой, состоит в том, чтобы
загрузить координату X в регистр С, а координату Y - в регистр
В, а затем вызвать процедуру PLOT_SUB, расположенную по адресу
22E5H (8933). Если у Вас координаты позиции печати точки уже
содержатся в системной переменной COORDS (5C7D = 23677), то
входить в эту процедуру можно в точке 22E8H (8936). Обратите
внимание на то, что когда процедуры ПЗУ вычисляют по
координатам позиции печати адрес соответствующего байта в
дисплейной памяти, они коррумпируют регистр HL. Если он Вам
нужен, его надо сохранить на стеке и потом восстановить.
Другой метод может быть более приемлем для тех энтузиас-
тов, которые работают со встроенным калькулятором. Обе коорди-
наты должны быть предварительно помещены на вершину стека
калькулятора в порядке: сначала x, затем y. Вызовом процедуры
PLOT (22DCH = 8924) эти координаты снимаются со стека и точка
печатается на экране.
2.8.5 Рисование линий.
Здесь также существуют два метода работы из машинного
кода, но прежде, чем мы их рассмотрим, напомним, что в операто-
ре БЕЙСИКа DRAW x,y параметры x и y не являются координатами
экрана, а являются "смещением" точки конца отрезка относительно
точки его начала. "Смещение" может быть не только положитель-
ным, но и отрицательным.
Метод 1.
~~~~~~~~
"Смещение" x загружается в регистры C и Е. При этом в
регистре C устанавливается его абсолютная величина - ABS (x), а
в регистре Е устанавливается 01, если "смещение" положительно
или равно нулю или FFH, если отрицательно.
Аналогично "смещение" y загружается в регистры B и D. В
регистре B - ABS (y), а в регистре D - 01 или FFH.
После этого можно рисовать линию, вызвав процедуру
DRAW_LINE с точкой входа 24BAH (9402). Линия будет нарисована,
но следует предусмотреть сохранение регистровой пары H'L'
(альтернативная), т.к. она будет коррумпирована.
Метод 2.
~~~~~~~~
Второй путь, как и для печати точек, состоит в использова-
нии калькулятора. Смещения x и y (в таком порядке) должны быть
установлены на вершине стека калькулятора и тогда та же проце-
дура DRAW_LINE, но с точкой входа 24B7 (9399) нарисует отрезок
прямой на экране. H'L' здесь коррумпируется точно так же.
2.8.6 Рисование дуги.
Оператор БЕЙСИКа DRAW может вычерчивать между двумя
точками не только прямые линии, но и соединять их с помощью
дуги. Форма оператора - DRAW x,y,a. Параметр a определяет
угловую меру дуги, а x,y - "смещения". Угловая мера "a"
задается в радианах.
Чтобы выполнить аналогичную задачу из машинного кода,
следует все три параметра поместить на стек встроенного кальку-
лятора в порядке x, y, a. Затем вызывается процедура DRAW_ARC
(2394H = 9108). Дуга рисуется, как серия очень маленьких пря-
мых, т.е. эта процедура в своей работе многократно вызывает
процедуру DRAW_LINE и, следовательно, регистровая пара H'L'
(альтернативная) также неизбежно коррумпируется.
2.8.7 Рисование окружности.
Здесь тоже ведется работа через встроенный калькулятор.
Координаты центра окружности x и y, а затем радиус r должны
быть помещены на вершину стека калькулятора, после чего
выполняется вход в процедуру CIRCLE через точку входа 232DH
(9005) для изображения окружности. H'L' - коррумпируется.
2.8.8 Сканирование экрана.
Проверка пиксела.
~~~~~~~~~~~~~~~~~
С помощью функции POINT (x,y) Вы можете проверить включен
или выключен пиксел экрана с координатами x,y. Для имитации
работы этой функции из машинного кода у Вас есть два пути.
Во-первых, Вы можете прогрузить регистры B и С координатами x и
y, после чего вызвать процедуру POINT_SUB с точкой входа (22CЕH
= 8910), а во-вторых, можете установить x и y на вершине стека
калькулятора и вызвать эту же процедуру с точкой входа 22CBH
(8907). И в том и в другом случае результат будет оставлен на
вершине стека. Снять его оттуда можно, обратившись к процедуре
ПЗУ FP_TO_A (2DD5H = 11733). Эта процедура перешлет результат в
регистр А процессора. Если пиксел выключен, то есть имеет цвет
PAPER, Вы получите 0, а если он включен, т.е. имеет цвет INK,
Вы получите единицу.
Проверка атрибутов экрана.
~~~~~~~~~~~~~~~~~~~~~~~~~~
С помощью функции ATTR (Y,X) Вы можете проверить установку
атрибутов в заданном знакоместе с координатами Y,X. Здесь Y -
номер экранного ряда (1...22), а X - номер столбца (1...32).
Для имитации работы этой функции из машинного кода Вы можете
загрузить регистры B и С координатами X и Y, после чего
вызвать процедуру S_ATTR_S с точкой входа (2583H = 9603), а
во-вторых, можете установить Y и X на вершине стека
калькулятора и вызвать эту же процедуру с точкой входа 2580H
(9600). И в том, и в другом случае результат будет оставлен на
вершине стека. Снять его оттуда можно, обратившись к процедуре
ПЗУ FP_TO_A (2DD5H = 11733), которая перешлет результат в
аккумулятор. Анализируя данные по битам, Вы сможете установить
параметры цветовых атрибутов в заданном знакоместе. Раскладку
по битам см. на Рис.8 (стр.16).
Проверка содержимого заданного знакоместа.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
В БЕЙСИКе Вы можете воспользоваться функцией SCREEN$ (Y,X)
для того, чтобы определить, есть ли какой-нибудь символ ASCII в
данном знакоместе с координатами Y и X и если есть, то что это
за символ. То есть, эта функция может исполнять сканирование
экрана. Надо, правда, сказать, что работа этой функции в БЕЙСИ-
Ке не отличается надежностью. В работе активно используется
стек калькулятора, на котором может образовываться такая пута-
ница, что например IF STRING$ (0,0)=STRING$(0,1) THEN PRINT
"TRUE" будет всегда выдавать "TRUE" независимо от того, что
содержится в знакоместах (0,0) и (0,1).
К счастью, мы можем организовать сканирование и из машин-
ного кода, причем там такой путаницы не будет. Вы можете ис-
пользовать процедуру ПЗУ S_SCRN$_S либо с точкой входа 2535H
(9525), если Вы поместили Y и X на вершину стека калькулятора
(именно в таком порядке), либо с точкой входа 2538H (9528),
если Вы поместили в регистр C номер экранного ряда, а в В -
номер столбца.
И в том, и в другом случае результат будет оставлен на
вершине стека калькулятора. Чтобы переслать его оттуда в
регистры микропроцессора, воспользуйтесь процедурой FP_TO_AEDCB
(2BF1H = 11249). После этого в BC будет содержаться 0, если
такого символа в наборе ASCII не существует или 1, если символ
опознан. Узнать, что это за символ, можно, посмотрев содержимое
аккумулятора - там будет содержаться его код.
Конечно, в результате сканирования смогут быть разысканы
только символы ASCII - от 20H ("пробел") до 7FH ("копирайт"),
т.к. только они имеются в таблице шрифта, на которую указывает
системная переменная CHARS (23606 = 5C36H), но это дело можно
доработать. Мы приведем процедуру, которая разыщет не только
символы ASCII, но также и символы блочной графики и символы
графики пользователя. Назовем ее SCANER и приведем чуть позже,
в разделе 2.10. А пока надо оговорить еще несколько основопо-
лагающих моментов.