ZX-Ревю 1992 №7-8 1991 г.

Элементарная графика в машинных кодах - эмуляция команд БЕЙСИКа из машинного кода.


Темы статьи: Программирование  

Эмуляция команд БЕЙСИКа из машинного кода.

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

CLS

Сначала займемся очисткой экрана. В машинном коде это можно сделать вызовом процедуры CLS, расположенной в ПЗУ по адресу 0D6BH (3435). В результате ее работы выключаются все пикселы на экране, а цветовые атрибуты устанавливаются такими, как установлено в системной переменной ATTR_P 5С8DH (23693). Ее побитовая раскладка та же, что и у системной переменной ATTR_T (см. выше). Данная процедура работает точно так же, как и соответствующая команда БЕЙСИКа.

Вы можете также очистить только нижнюю часть экрана (обычно это две нижние строки). Это делается вызовом процедуры CLS_LOWER, которая находится по адресу 0D6EH (3438). В отличие от основного экрана, эта область очищается с цветом бордюра, а не с цветом, установленным в ATTR_P.

Среди процедур ПЗУ есть еще одна, обеспечивающая более мощные возможности. Она называется CL_LINE (0E44H = 3652) и очищает заданное количество строк в нижней части экрана.

Перед ее вызовом в регистре B должно быть установлено количество строк, подлежащих очистке от 01 до 18Н (от 1 до 24). Так, например, чтобы очистить 10 нижних строк, нужно предварительно в регистр B заслать число 0АН.

Эту процедуру можно применять двумя способами. Если нулевой бит системной переменной TVFLAG (5C3C = 23612) выключен, то при очистке используются цвета экрана, а если он включен, то используется цвет бордюра. Таким образом, здесь есть возможность очистить одновременно весь экран, включая и нижние две строки, в цвет ATTR_P. Процедура CLS сделать такого не может. В то же время, следует обратить внимание на то, что процедура CLS после очистки экрана инициализирует курсор и текущая позиция печати устанавливается в исходное положение - левый верхний угол. Процедура же CL_LINE этого не делает.

Скроллинг экрана.

Когда Вы пытаетесь напечатать что-либо за последней возможной позицией печати, то вместо результата получаете сообщение "scroll?" в нижней части экрана и компьютер ждет от Вас нажатие клавиши. Если это клавиша "N" или "BREAK", печать на экране прекращается с сообщением об остановке, в противном случае печать продолжается. Экран вроде бы заполнен, но печать возможна, происходит скроллинг вверх. Этот скроллинг происходит автоматически и длится до тех пор, пока вся информация, присутствовавшая на экране, когда выходило сообщение "scroll?", не скроется из виду за верхней кромкой экрана.

Такой вид скроллинга называется автоматическим и он существует на "Спектруме" как в БЕЙСИКе, так и в машинном коде.

Но возможен также и "ручной" скроллинг. Вызов процедуры CL_SC_ALL (0DFEH = 3582) "прокрутит" весь экран, но при этом возникнут несколько неожиданные эффекты:

- во-первых, позиция печати не изменится и останется там же, где была. С этим Вам придется разбираться вручную.

- во-вторых, если первая строка нижней части экрана (системного окна) не пуста или имеет цвет, отличный от цвета основного экрана, то результат может быть не совсем тем, какой Вы ожидаете.

Другой способ исполнения "ручного" скроллинга еще интереснее. Он базируется на использовании процедуры CL_SCROLL (0E00H 3584). С ее помощью можно "прокручивать" только часть экрана. Предварительно в регистр B надо занести количество строк, подлежащих скроллингу (обратите внимание на то, что изменено будет на одну строку больше). Минимальное количество строк - 1. В этом случае нижняя строка экрана будет поднята на одно знакоместо вверх, а снизу появится чистая строка. Для того, чтобы переработать весь экран, следует установить число 17H. Таким образом, действие этой команды состоит в перемещении на одну позицию вверх "B" нижних строк и в очистке нижней строки.

PAUSE

БЕЙСИК-оператор PAUSE можно легко эмулировать в машинном коде. Единицей измерения времени в "Спектруме" являются пятидесятые доли секунды (потому, что частота переменного тока в нашей сети 50Гц. Если бы Вы жили в Англии, то у Вас в секунду проходило бы не 50, а 60 прерываний работы процессора, т. к. там частота сети равна 60 Гц6).

Для того, чтобы исполнить паузу на m пятидесятых долей секунды, Вам достаточно загрузить это число m в регистровую пару ВС, а затем вызвать процедуру ПЗУ PAUSE_1, расположенную по адресу 1F3DH (7997). Работая, процедура обеспечит заданную паузу. Во время своей работы процедура регулярно опрашивает системную переменную FLAGS (5C3BH = 23611). Ее пятый бит, если он включен, свидетельствует о том, что произошло нажатие клавиши. Таким образом, пауза может быть прервана нажатием любой клавиши -все, как в стандартном БЕЙСИКе. Если Вы зашлете в регистровую пару BC ноль, то установленная пауза будет неограниченной, то есть до нажатия клавиши.

Вам, может быть, потребуется случай, когда пауза должна быть выдержана в течение заданного времени и не должна прерываться нажатием клавиши, поможет несложная процедура (листинг 6).

Зашлите в BC требуемую величину задержки и вызывайте эту процедуру.

78 PAUSE LD A, B

B1 OR C

С8 RET Z

0B DEC BC

76 HALT

18F9 JR PAUSE

Листинг 6.

Проверка BC на ноль.

Выход, если так. Уменьшение BC, Задержка на 1/50 секунды (точнее - до следующего прерывания, которое пройдет чуть быстрее). Возврат для повтора.

Рисование точек.

Для изображения точек на экране из машинного кода есть два приема. Первый, и наиболее простой состоит в том, чтобы загрузить координату X в регистр C, а координату Y -в регистр B, а затем вызвать процедуру PLOT_SUB, расположенную по адресу 22Е5Н (8933). Если у Вас координаты позиции печати точки уже содержатся в системной переменной COORDS (5C7D = 23677), то входить в эту процедуру можно в точке 22Е8Н (8936). Обратите внимание на то, что когда процедуры ПЗУ вычисляют по координатам позиции печати адрес соответствующего байта в дисплейной памяти, они коррумпируют регистр HL. Если он Вам нужен, его надо сохранить на стеке и потом восстановить.

Другой метод может быть более приемлем для тех энтузиастов, которые работают со встроенным калькулятором. Обе координаты должны быть предварительно помещены на вершину стека калькулятора в порядке: сначала X, затем Y. Вызовом процедуры PLOT (22DCH = 8924) эти координаты снимаются со стека и точка печатается на экране.

Рисование прямых линий.

Здесь также существуют два метода работы из машинного кода, но прежде, чем мы их рассмотрим, напомним, что в операторе БЕЙСИКа DRAW X, Y параметры X и Y не являются координатами экрана, а являются "смещением" точки конца отрезка относительно точки его начала. "Смещение" может быть не только положительным, но и отрицательным.

Метод 1.

"Смещение" X загружается в регистры C и Е. При этом в регистре C устанавливается его абсолютная величина ABS (X), а в регистре E устанавливается 01, если "смещение" положительно или равно нулю, но FFH, если отрицательно. Аналогично "смещение" Y загружается в регистры B и D. В регистре B - ABS (Y), а в регистре D - 01 или FFH.

После этого можно рисовать линию, вызвав процедуру DRAW_LINE с точкой входа 24BAH (9402). Линия будет нарисована, но следует предусмотреть сохранение регистровой пары H'L' (альтернативная), т.к. она будет коррумпирована. Второй путь, как и для печати точек, состоит в использовании калькулятора. Смещения X и Y (в таком порядке) должны быть установлены на вершине стека калькулятора и тогда та же процедура DRAW_LINE, но с точкой входа 24В7 (9399) нарисует отрезок прямой на экране. H'L' здесь коррумпируется точно так же.

Рисование дуги.

Оператор Бейсика DRAW может вычерчивать между двумя точками не только прямые линии, но и соединять их с помощью дуги. Форма оператора - DRAW X,Y,A. Параметр A определяет угловую меру дуги, а X, Y - "смещения". Угловая мера "А" задается в радианах.

Чтобы выполнить аналогичную задачу из машинного кода, следует все три параметра поместить на стек встроенного калькулятора в порядке X, Y, A. Затем вызывается процедура DRAW_ARC (2394Н = 9108). Дуга рисуется, как серия очень маленьких прямых, т.е. эта процедура в своей работе многократно вызывает процедуру DRAW_LINE и, следовательно, регистровая пара H'L' (альтернативные) также неизбежно коррумпируется.

Рисование окружности.

Здесь тоже ведется работа через встроенный калькулятор. Координаты центра окружности X и Y, а затем радиус R должны быть помещены на вершину стека калькулятора, а затем выполняется вход в процедуру CIRCLE через точку входа 232DH (9005) для изображения окружности. H'L'- коррумпируется.

Проверка точки экрана.

С помощью функции POINT (X,Y) Вы можете проверить включен или выключен пиксел экрана с координатами X, Y. Для имитации работы этой функции из машинного кода у Вас есть два пути. Во-первых, Вы можете прогрузить регистры B и C координатами X и Y, после чего вызвать процедуру POINT_SUB с точкой входа (22CEH = 8910), а во-вторых, можете установить X и Y на вершине стека калькулятора и вызвать эту же процедуру с точкой входа 22CBH (8907). И в том и в другом случае результат будет оставлен на вершине стека. Снять его оттуда можно, обратившись к процедуре ПЗУ FP_TO_A (2DD5H = 11733). Эта процедура перешлет результат в регистр A процессора. Если пиксел выключен, то есть имеет цвет PAPER, Вы получите 0, а если он включен, т. е. имеет цвет INK, Вы получите единицу.

Проверка атрибутов экрана.

С помощью функции ATTR (Y,X) Вы можете проверить установку атрибутов в заданном знакоместе с координатами Y, X. Здесь X -номер экранного ряда (1...24), a Y - номер столбца (1...32). Для имитации работы этой функции из машинного кода Вы можете загрузить регистры B и C координатами Y и X, после чего вызвать процедуру S_ATTR_S с точкой входа (2583Н = 9603), а во-вторых, можете установить Y и X на вершине стека калькулятора и вызвать эту же процедуру с точкой входа 2580Н (9600). И в том, и в другом случае результат будет оставлен на вершине стека, снять его оттуда можно, обратившись к процедуре ПЗУ FP_TO_A (2DD5H = 11733), которая перешлет результат в аккумулятор. Анализируя данные по битам, Вы сможете установить параметры цветовых атрибутов в заданном знакоместе.

Раскладку по битам см. на рис. 3.

Проверка содержимого заданного знакоместа.

В БЕЙСИКе вы можете воспользоваться функцией SCREEN$ (Y,X) для того, чтобы определить, есть ли какой-нибудь символ ASCII в данном знакоместе с координатами Y и X и если есть, то что это за символ. То есть, эта функция может исполнять сканирование экрана. Надо, правда, сказать, что работа этой функции в БЕЙСИКе не отличается надежностью. В работе активно используется стек калькулятора, на котором может образовываться такая путаница, что например IF STRING$ (0,0)=STRING$(0, 1) THEN PRINT "TRUE" будет всегда выдавать "TRUE" независимо от того, что содержится в знакоместах (0,0) и (0,1).

К счастью, мы можем организовать сканирование и из машинного кода, причем там такой путаницы не будет. Вы можете использовать процедуру ПЗУ S_SCRN$_S либо с точкой входа 2535Н (9525), если Вы поместили Y и X на вершину стека калькулятора (именно в таком порядке), либо с точкой входа 2538H (9528), если вы поместили в регистр C номер экранного ряда, а в B - номер столбца.

И в том, и в другом случае результат будет оставлен на вершине стека калькулятора. Чтобы переслать его оттуда в регистры микропроцессора, воспользуйтесь процедурой FP_TO_AEDCB (2BF1H = 11249). После этого в BC будет содержаться 0, если такого символа в наборе ASCII не существует или 1, если символ опознан. Узнать, что это за символ, можно посмотрев содержимое аккумулятора - там будет содержаться его код.

Конечно, в результате сканирования смогут быть разысканы только символы ASCII - от 20Н ("пробел") до 7FH ("копирайт"), т.к. только они имеются в таблице шрифта, на которую указывает системная переменная CHARS (23606 -5С36Н), но это дело можно доработать. Мы не приводим здесь процедуру, которая способна просканировать весь экран и определить как символы ASCII, так и символы графики пользователя и символы блочной графики в связи с нехваткой места. Будущие читатели смогут познакомиться и с ней и с многими другими интересными и полезными вещами на страницах нашей новой книги.

(С) ИНФОРКОМ 1992




СОДЕРЖАНИЕ:


  Оставте Ваш отзыв:

  НИК/ИМЯ
  ПОЧТА (шифруется)
  КОД



Темы: Игры, Программное обеспечение, Пресса, Аппаратное обеспечение, Сеть, Демосцена, Люди, Программирование

Похожие статьи:
С миру по биту - Статья-пародия на различные виды описаний игр "Краткий путеводитель по описаниям игр".
Новости - о системке "Paracels Protection System v1.0", местные новости.
Enlight'97 - Предварительная информация о проведении кокурса Enlight. Общие правила для всех конкурсов на всех платформах.
Сам себе Пушкин - Алексей Кубрак, Алексей Гастев, Игорь Северянин, Фёдор Тютчев, Борис Поплавский, Алексей Конаков, Борис Косенков, Oксана Кряжова, Eвгений Борисов.
Обзор - прохождение игры Blinky's.

В этот день...   23 апреля