1.4 ГРАФИКА ПОЛЬЗОВАТЕЛЯ
1.4.1 Работа с графикой пользователя.
Пользователь компьютера, совместимого с ZX-Spectrum может
несколько раширить доступный ему набор символов, использовав
для этого так называемые символы графики пользователя.
В верхних областях памяти компьютера, начиная с адреса
65368 и по адрес 65535 находится оласть UDG-графики (графики
пользователя). Она занимает 168 байтов и, поскольку на каждый
символ расходуется по 8 байтов, то есть возможность задать 21
символ.
На адрес начала графики пользователя указывает системная
переменная UDG, находящаяся по адресу 23675 (5C7BH). Конец
области графики пользователя - это физический конец оперативной
памяти компьютера, на который указывает системная переменная
P_RAMT (23732 = 5CB4H).
На клавиатуре компьютера эти символы "привязаны" к
клавишам от A до U в алфавитном порядке и выдается на экран
каждый символ нажатием на соответствующую клавишу, но делать
это надо, когда компьютер находится в графическом режиме, т.е.
стоит графический курсор "G". Этот режим включается и выключа-
ется одновременным нажатием на клавиши CAPS SHIFT и "9".
Вы можете в любое время проверить это например на клавише
"A", но ничего интересного, кроме символа "A" не получите,
поскольку пока не сформировали в области UDG ни одного шаблона.
Рассмотрим работу с графикой пользователя на конкретном
примере. Предположим, Вы хотите изобразить вертолет, имеющий
размер 24 X 16 пикселов и занимающий на экране 6 знакомест.
Следовательно, наша задача так задать шаблоны шести символов
UDG (A,B,C,D,E,F), чтобы распечатанные на экране в следующем
порядке, они образовали бы вертолет (рис. 9).
----T---T---¬
¦ A ¦ B ¦ C ¦
+---+---+---¦
¦ D ¦ E ¦ F ¦
L---+---+----
----------------T---------------T----------------¬
¦ A ¦ B ¦ C ¦
¦ ¦ X X ¦ ¦
¦X X X X X X X X¦X X X X X X X X¦X X X X X ¦
¦ ¦ X X ¦ ¦
¦ X X¦X X X X ¦ X X ¦
¦ X ¦X X X X X X ¦ X X X ¦
¦ X ¦X X X X X X X X¦X X X X X X ¦
¦_____ X________¦X___X____ X_X_X¦X_X_X_______X___¦
¦ X X X X X X¦X X X X X¦ X ¦
¦ X X ¦X X X X X X X ¦ ¦
¦ X X X¦X X X X X X X ¦ ¦
¦ X X X X¦X X X X X X ¦ ¦
¦ X ¦ X ¦ ¦
¦ X X X X X X¦X X X X X X ¦ ¦
¦ ¦ ¦ ¦
¦ D ¦ E ¦ F ¦
L---------------+---------------+-----------------
Рис. 9
Рассмотрим подробно как создается шаблон на примере гра-
фического символа "B" (рис. 10).
Таким образом, нам достаточно заслать в адреса, начиная с
которых располагается символ графики пользователя "B" восемь
байтов 0, 96, 255, 96, 240, 248, 255, 167 и клавиша "B" в гра-
фическом режиме будет определена. Осталось только разыскать
адрес, начиная с которого должен быть размещен этот восьмибайт-
ный шаблон.
Здесь нам поможет "Спектрумовская" функция USR. Она для
того и служит, чтобы отыскивать адреса шаблонов символов графи-
ки пользователя.
128 64 32 16 8 4 2 1
----T---T---T---T---T---T---T---¬
¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦ 0000 0000 = 0
+---+---+---+---+---+---+---+---+
¦ ¦ X ¦ X ¦ ¦ ¦ ¦ ¦ ¦ 0110 0000 = 96
+---+---+---+---+---+---+---+---+
¦ X ¦ X ¦ X ¦ X ¦ X ¦ X ¦ X ¦ X ¦ 1111 1111 = 255
+---+---+---+---+---+---+---+---+
¦ ¦ X ¦ X ¦ ¦ ¦ ¦ ¦ ¦ 0110 0000 = 96
+---+---+---+---+---+---+---+---+
¦ X ¦ X ¦ X ¦ X ¦ ¦ ¦ ¦ ¦ 1111 0000 = 240
+---+---+---+---+---+---+---+---+
¦ X ¦ X ¦ X ¦ X ¦ X ¦ ¦ ¦ ¦ 1111 1000 = 248
+---+---+---+---+---+---+---+---+
¦ X ¦ X ¦ X ¦ X ¦ X ¦ X ¦ X ¦ X ¦ 1111 1111 = 255
+---+---+---+---+---+---+---+---+
¦ X ¦ ¦ X ¦ ¦ ¦ X ¦ X ¦ X ¦ 1010 0111 = 167
L---+---+---+---+---+---+---+----
Рис. 10
Команда PRINT USR "b" - даст Вам этот адрес, хотя он Вам
и не очень нужен. От Вас ведь требуется только заслать туда 8
байтов. Организуйте цикл:
10 FOR i = 0 TO 7
20 READ a: POKE USR "b"+i, a
30 NEXT i
40 DATA 0, 96, 255, 96, 240, 248, 255, 167
Точно так же можно задать и остальные символы A,C,D,E,F.
Для справки, если Вы захотите изобразить вертолет, приводим их
шаблоны.
A: 0, 0, 255, 0, 3, 4, 8, 16
C: 0, 0, 248, 0, 18, 14, 252, 226
D: 63, 48, 49, 15, 4, 63, 0, 0
E: 167, 254, 254, 252, 32, 252, 0, 0
F: 1, 0, 0, 0, 0, 0, 0, 0
Сам же вертолет будет напечатан например так:
100 PRINT AT 10,15 "ABC"
110 PRINT AT 11,15 "CDE"
Не забудьте только, что символы от A до E набираются в
графическом режиме.
1.4.2. Создание банков символов графики пользователя.
Символы графики пользователя в умелых руках могут дать
очень многое. С их помощью можно в кратчайшие сроки сделать
модель будущей аркадной игры, разработать полноценную программу
для деловых приложений и многое многое другое. Существенный
недостаток их состоит в том, что 21 символ - это не очень мно-
го, но делу можно помочь. Вы можете, например, иметь несколько
заготовленных заранее банков символов и по мере необходимости
переключаться с одного банка на другой, что выполняется путем
подстановки заданного банка на место текущего.
Каждый банк имеет размер 21*8 =168 байтов и перброска их
из того места, где они хранятся, в область, отведенную для
символов UDG, может занять определенное время, если эту опера-
цию делать на БЕЙСИКе, поэтому здесь мы используем небольшую
процедуру в машинном коде.
Символы UDG хранятся в четырех банках. Программа позволяет
записывать содержимое области UDG в эти банки или, наоборот,
выполнять загрузку того, что в них находится в область памяти,
отведенную для символов графики пользователя, причем делать это
можно как из БЕЙСИК-программы, так и с помощью прямой команды.
Команды имеют следующий формат:
- для записи данных в банк n (n=1...4):
RANDOMIZE USR address: REM Wn
- для считывания данных из банка n:
RANDOMIZE USR address: REM Ln
Параметр address - адрес, с которого начинается приведен-
ная ниже программа. С этим адресом связаны и адреса, в которых
располагаются четыре банка символов UDG. Вы можете сами задать
тот адрес, который Вам удобен, внеся изменения в нижеприведен-
ный код, а можете воспользоваться тем, который уже задан. Нами
установлен начальный адрес 64000. Если Вы захотите его изме-
нить, Вам надо будет поменять те значения в строках DATA,
которые помечены знаком "*".
Конечно, при наборе строк DATA знак "*" набирать не нужно.
Бейсик-загрузчик.
5 LET addr = 640000
10 CLEAR addr-1
20 FOR k = addr TO addr+16: READ a: POKE k,a: NEXT k
30 FOR k = addr+30 TO addr+47: READ a: POKE k,a: NEXT k
40 FOR k = addr+60 TO addr+77: READ a: POKE k,a: NEXT k
50 DATA 42, 93, 92, 35, 35
60 DATA 126, 254, 87, 202, *30
70 DATA *250, 254, 76, 202, *60
50 DATA *250, 201, 35, 126, 214
80 DATA 48, 33, 88, 255, 17
90 DATA 0,*250, 130, 87, 1
100 DATA 168, 0, 237, 176, 201
110 DATA 35, 126, 214, 48, 17
120 DATA 88, 255, 33, 0,*250
130 DATA 132, 103, 1, 168, 0
140 DATA 237, 176, 201
Дисассемблер программы:
64000 2A5D5C LD HL,(5C5DH) ; 5C5DH=23645 DEC. Это ад-
;рес системной переменной
;CH_ADD. Во время работы
;БЕЙСИК-программы она со-
;держит адрес очередного
;символа обрабатываемой
;БЕЙСИК-строки.
;Поскольку у нас исполняе-
;ется RANDOMIZE USR, то
;эта системная переменная
;указывает на символ ":"
;(двоеточие).
64003 23 INC HL ;Теперь HL указывает на
;ключевое слово REM.
64004 23 INC HL ;HL указывает на символ,
;стоящий за REM. Это либо
;"W", либо "L".
64005 7E LD A,(HL) ;Приняли его в аккумулятор
64006 FE57 CP 57H ;Сравнили его с 57H.
;57H=87 DEC - это код бук-
;вы "W".
*64008 CA1EFA JP Z,FA1EH ;Если это он, то переход
;на адрес FA1EH = 64030.
64011 FE4C CP 4CH ;Сравнили его с 4CH.
;4CH=76 DEC - это код бук-
;вы "L".
*64013 CA3CFA JP Z,FA3CH ;Если это он, то переход
;на адрес FA3CH = 64060.
64016 C9 RET ;Возврат в БЕЙСИК.
В эту подпрограмму мы попадаем, если была подана команда
RANDOMIZE USR addr: REM Wn, то есть речь идет о записи символь-
ного набора из области UDG в n-ый ,банк памяти.
64030 23 INC HL ;Теперь HL указывает на
;символ, стоящий после "W"
;Там должна быть цифра от
;1 до 4.
64031 7E LD A,(HL) ;Приняли символ этой цифры
;в аккумулятор.
64032 D630 SUB 30H ;Отняли 30H (48 DEC). Дело
;в том, что символы цифр
;начинаются с 48-го кода.
;Код 48 соответствует
;цифре "0". Сделав это
;вычитание, мы получим
;вместо кода цифры - саму
;цифру.
64034 2158FF LD HL,FF58H ;Установили в HL указание
;на адрес FF58H=65368 DEC.
;В "Спектруме" стандартно
;с этого адреса начинаются
;шаблоны символов UDG.
*64037 1100FA LD DE, FA00H ;Установили в DE адрес
;64000.
64040 82 ADD A,D ;
64041 57 LD D,A ;Теперь DE содержит адрес,
;равный 64000+256*n, где
;n -номер банка (1...4).
64042 01A800 LD BC,00A8 ;Счетчик перемещаемых
;байтов - A8H=168 DEC.
64045 EDB0 LDIR ;Блочное перемещение
;168 байтов из адреса,
;на который указывает HL
;в адрес, на который
;указывает DE.
64047 C9 RET ;Возврат.
В эту подпрограмму мы попадаем, если была подана команда
RANDOMIZE USR addr: REM Ln, то есть речь идет о записи символь-
ного набора из n-го банка памяти в область UDG.
64060 23 INC HL ;Теперь HL указывает на
;символ, стоящий после "L"
;Там должна быть цифра от
;1 до 4.
64061 7E LD A,(HL) ;Приняли код этой цифры.
64062 D630 SUB 30H ;Отняли 30H (48 DEC),
;и получили вместо кода
;цифры - саму цифру.
64064 1158FF LD DE,FF58H ;Установили в DE указание
;на адрес FF58H = 65368
;(это начало области UDG).
*64067 2100FA LD HL,FA00H ;Установили в HL указание
;на адрес 64000.
64070 84 ADD A,H ;
64071 67 LD H,A ;Теперь в HL содержится
;адрес 64000+256*n, где
;n-номер банка (1...4).
64072 01A800 LD BC,00A8 ;Счетчик перемещаемых
;байтов - A8H=168 DEC.
64075 EDB0 LDIR ;Блочное перемещение
;168 байтов из адреса,
;на который указывает HL
;в адрес, на который
;указывает DE.
64077 C9 RET ;Возврат.
Если Вы избрали для хранения этой процедуры адрес ADDR, то
первый банк будет храниться, начиная с ADDR + 256, второй -
начиная с ADDR + 512 и т.д. Если же Вы желаете изменить
исходный адрес ADDR, то Вам надо будет внести изменения в
строки, помеченные знаком "*".