Как известно, любой программе нужно удобное управление. Особенно удобно, если выбор режимов и команд производится джойстиком. Ниже приведена процедура, которая перемещает по экрану стрелочку и принажатии кнопки "огонь" имеет на выходе в регистровой паре HL адрес в дисплейном файле, соответствующий кончику стрелки ив регистровой паре ВС соответствующий адрес в области атрибутов. Эти адреса можно лихо использовать для определения дальнейших действий. Например, имея адрес атрибутов, можно проверить, скажем, бит 6 - яркость, попали ли Вы на команду или стрелка болтается, где ни попадя. Буду очень рад, если приведенная программка кому-нибудь пригодится.
|
00020 |
; Написана в |
августе 1993г | ||
|
00030 |
; Провидения | |||
|
00040 |
; автор |
Риккер В.В. | ||
|
00050 |
; | |||
|
00060 |
ORG |
40000 |
;нужный адрес ассемблирования | |
|
00070 |
ENT | |||
|
00080 |
EI | |||
|
00090 |
JP |
START | ||
|
п П 1 п п 00100 | ||||
|
00110 | ||||
|
00120 | ||||
|
00130 |
; * Переменные программах * | |||
|
00140 | ||||
|
00150 |
; | |||
|
00160 |
BUFFS |
DEFS |
30 |
;Буфер для сохранения того, |
|
;что под стрелкой на экране. | ||||
|
00170 |
STS |
DEFW |
0 |
;Адрес в видеообласти, соответствующий |
|
;острию стрелки. | ||||
|
00180 |
CRDS |
DEFW |
0 |
;Координаты острия стрелки. |
|
00190 |
; | |||
|
00200 |
; |
Шаблоны стрелки | ||
|
00210 |
; | |||
|
00220 |
ORSH |
DEFB |
#C0,#E0,#F0 |
;Шаблон для операции OR |
|
00230 |
DEFB |
#F8,#FC, #FE | ||
|
00240 |
DEFB |
#FF,#FE, #FC | ||
|
00250 |
DEFB |
#1C,#0E,#0E | ||
|
00260 |
DEFB |
#07,#07,#03 | ||
|
00270 |
XORSH |
DEFB |
#C0,#A0,#90 |
;Шаблон для операции XOR |
|
00280 |
DEFB |
#88,#84,#82 | ||
|
00290 |
DEFB |
#81,#86,#B4 | ||
|
00300 |
DEFB |
#14,#0A, #0A | ||
|
00310 |
DEFB |
#05,#05,#03 | ||
|
00320 |
; | |||
|
00330 |
STEP |
EQU |
2 |
;Скорость перемещения стрелки |
|
;(с увеличением скорости | ||||
|
;уменьшается точность) | ||||
|
nm/i п 00340 | ||||
|
00350 | ||||
|
00360 |
. * |
Подпрограммы * | ||
|
00370 | ||||
|
00380 |
; | |||
|
00390 |
SCRBF |
LD |
HL,(CRDS) |
;Координаты острия стрелки. |
|
00400 |
LD |
C,H |
;Подготавливаем регистры для вы | |
|
00410 |
LD |
B, L |
числения адреса по координатам. | |
|
00420 |
LD |
A, B | ||
|
00430 |
CALL |
#22B1 |
;Вычисляем адрес (процедура ПЗУ). | |
|
00440 |
LD |
(STS),HL |
;Сохраняем полученный адрес. | |
|
00450 |
LD |
DE, BUFFS |
;В DE адрес буфера. | |
|
00460 |
RB0 |
LD |
B,15 |
;Высота стрелки в пикселах. |
|
00470 |
RB1 |
PUSH |
HL | |
|
00480 |
LD |
C, 2 |
;Сколько смежных байт сохранять. | |
|
00490 |
RB2 |
LD |
A,(HL) | |
|
00500 |
LD |
(DE) ,A | ||
|
00510 |
INC |
L | ||
|
00520 |
INC |
DE | ||
|
00530 |
DEC |
C | ||
|
00540 |
JR |
NZ,RB2 | ||
|
00550 |
POP |
HL | ||
|
00560 |
CALL |
DAD1 |
;Получаем адрес в дисплейном ;файле на 1 пиксел ниже. | |
|
00570 |
DJNZ |
RB1 | ||
|
00580 |
RET | |||
|
00590 |
в | |||
|
; | ||||
|
00600 |
DAD1 |
INC |
H | |
|
00610 |
LD |
A, H | ||
|
00620 |
AND |
7 | ||
|
00630 |
RET |
NZ | ||
|
00640 |
LD |
A, H | ||
|
00650 |
SUB |
8 | ||
|
00660 |
LD |
H, A | ||
|
00670 |
LD |
A, L | ||
|
00680 |
ADD |
A,32 | ||
|
00690 |
LD |
L,A | ||
|
00700 |
RET |
NC | ||
|
00710 |
LD |
A, H | ||
|
00720 |
ADD |
A, 8 | ||
|
00730 |
LD |
H, A | ||
|
00740 |
RET | |||
|
00750 |
в | |||
|
; | ||||
|
00760 |
BFSCR |
LD |
HL,#771A |
;Подпрогр. восстановления экрана. |
|
00770 |
LD |
(RB2),HL |
;Сначала перепрограммируется ;процедура SCRBF. | |
|
00780 |
CALL |
SCRBF | ||
|
00790 |
LD |
HL,#127E |
;Восстанавл. код процедуры SCRBF. | |
|
00800 |
LD |
(RB2),HL | ||
|
00810 |
RET | |||
|
00820 | ||||
|
00830 |
; Подпрограмма |
создания образа стрелки | ||
|
00840 |
; по имеющимся |
координатам | ||
|
00850 |
FORM |
LD |
A,(CRDS+1) |
;По горизонт. координате получаем |
|
00860 |
AND |
7 |
;номер бита в байте экрана. | |
|
00870 |
EX |
AF, AF' |
;Сохраняем его. | |
|
00880 |
LD |
IX,ORSH |
;Накладываем маску по OR. | |
|
00890 |
CALL |
FORMS | ||
|
00900 |
LD |
IX, MS3 | ||
|
00910 |
LD |
(IX+0),#AA |
;Изменяем процедуру FORMS. | |
|
00920 |
LD |
(IX+9) ,#AB | ||
|
00930 |
PUSH |
IX | ||
|
00940 |
LD |
IX,XORSH |
/Накладываем маску по XOR. | |
|
00950 |
CALL |
FORMS | ||
|
00960 |
POP |
IX | ||
|
00970 |
LD |
(IX+0),#B2 |
;Восстанавл. код процедуры FORMS. | |
|
00980 |
LD |
(IX+9) ,#B3 | ||
|
00990 |
RET | |||
|
01000 |
FORMS |
LD |
C,15 |
;Число линий в стрелке. |
|
01010 |
LD |
HL,(STS) |
;Берем адрес в экране. | |
|
01020 |
MS1 |
LD |
D,B |
;Обнуляем DE. |
|
01030 |
LD |
E,B | ||
|
01040 |
EX |
AF, AF' | ||
|
01050 |
LD |
B, A |
;В рег.В номер бита в адр.экрана. | |
|
01060 |
EX |
AF, AF' | ||
|
01070 |
DEC |
B |
;Проверяем его на ноль. | |
|
01080 |
INC |
B | ||
|
01090 |
LD |
D,(IX+0) |
;В DE байт из шаблона стрелки. | |
|
01100 |
JR |
Z, MS21 |
;Если 0, то обходим ротацию DE. | |
|
01110 |
MS2 |
SRL |
D |
;Сдвигаем шаблон. |
|
01120 |
RR |
E | ||
|
01130 |
DJNZ |
MS2 | ||
|
01140 |
MS21 |
LD |
A,(HL) |
;Накладываем полученную маску. |
|
01150 |
MS3 |
OR |
D |
;Команды OR D и OR E заменяются |
|
;на XOR D и XOR E и обратно. | ||||
|
01160 |
LD |
(HL),A | ||
|
01170 |
INC |
L |
;Переходим к следующему байту. | |
|
01180 |
LD |
A, L | ||
|
01190 |
AND |
#1F |
;Если вышли за правую границу | |
|
01200 |
JR |
Z, MS4 |
;экрана, то обход. | |
|
01210 |
LD |
A, (HL) |
;Иначе накладываем маску и на | |
|
;соседний байт. | ||||
|
01220 |
OR |
E | ||
|
01230 |
LD |
(HL),A | ||
|
01240 |
MS4 |
DEC |
L |
;Переходим на нижнюю линию |
|
01250 |
INC |
IX |
;и на следующий байт в шаблоне. | |
|
01260 |
CALL |
DAD1 | ||
|
01270 |
LD |
A, H |
;Проверяем, вышли ли | |
|
01280 |
CP |
#58 |
;за низ экрана. | |
|
01290 |
RET |
NC |
;ДА - выход. | |
|
01300 |
DEC |
C |
;НЕТ - уменьшаем счетчик строк | |
|
01310 |
JR |
NZ,MS1 |
;в стрелке и повторяем фокус. | |
|
01320 |
RET | |||
|
П 1 Я. "3 п | ||||
|
013 3 0 | ||||
|
01340 | ||||
|
01350 |
* Головная программа * | |||
|
01360 | ||||
|
01370 | ||||
|
01380 |
START |
LD |
HL,#64 64 |
;Начальные координаты стрелки. |
|
01390 |
LD |
(CRDS),HL | ||
|
01400 |
PUSH |
IX | ||
|
01410 |
Q0 |
CALL |
SCRBF |
; Сохраняем... |
|
01420 |
CALL |
FORM |
; Формируем... | |
|
01430 |
HALT |
; Отдыхаем... | ||
|
01440 |
IN |
A,(31) |
; Опрашиваем... | |
|
01450 |
PUSH |
AF | ||
|
01460 |
CALL |
BFSCR |
; Восстанавливаем^„ | |
|
01470 |
POP |
AF | ||
|
01480 |
LD |
C,A | ||
|
01490 |
LD |
E,STEP | ||
|
01500 |
LD |
D,254 |
;Задали максимум по Х. | |
|
01510 |
LD |
HL,CRDS+1 |
;Изменяем координаты согласно | |
|
01520 |
BIT |
0,C |
;тому, что нажали | |
|
01530 |
CALL |
NZ, PL |
;на джойстике. | |
|
01540 |
BIT |
1,C | ||
|
01550 |
CALL |
NZ,MIN | ||
|
01560 |
LD |
D, 190 |
;Максимум по Y. | |
|
01570 |
DEC |
HL |
;Перешли на координату Y. | |
|
01580 |
BIT |
2,C | ||
|
01590 |
CALL |
NZ, PL | ||
|
01600 |
BIT |
3,C | ||
|
01610 |
CALL |
NZ,MIN | ||
|
01620 |
BIT |
4,C | ||
|
01630 |
JR |
NZ,EXIT | ||
|
01640 |
JR |
Q0 | ||
|
01650 |
в | |||
|
; | ||||
|
01660 |
PL |
LD |
A,(HL) | |
|
01670 |
LD |
B, E | ||
|
01680 |
L0 |
CP |
D | |
|
01690 |
JR |
Z, END | ||
|
01700 |
INC |
A | ||
|
01710 |
DJNZ |
L0 | ||
|
01720 |
END |
LD |
(HL),A | |
|
01730 |
RET | |||
|
01740 |
в | |||
|
; | ||||
|
01750 |
MIN |
LD |
A,(HL) | |
|
01760 |
LD |
B, E | ||
|
01770 |
INP |
AND |
A | |
|
01780 |
JR |
Z, END | ||
|
01790 |
DEC |
A | ||
|
01800 |
DJNZ |
INP | ||
|
01810 |
LD |
(HL),A | ||
|
01820 |
RET | |||
|
01830 |
в | |||
|
; | ||||
|
01840 |
EXIT |
LD |
HL,(STS) | |
|
01850 |
PUSH |
HL | ||
|
01860 |
LD |
A, H | ||
|
01870 |
AND |
#18 | ||
|
01880 |
RRCA | |||
|
01890 |
RRCA | |||
|
01900 |
RRCA | |||
|
01910 |
OR |
#58 | ||
|
01920 |
LD |
B, A | ||
|
01930 |
LD |
C, L | ||
|
01940 |
POP |
HL | ||
|
01950 |
POP |
IX | ||
|
01960 |
RET |
01970 01980
; Конец программы
В строках 220-310 программы задается рисунок стрелки. Две маски (по OR и по XOR)
нужны для того, чтобы при попадании стрелки на область, закрашенную INK, стрелка не сливалась бы с фоном, а приобретала оконтуривание цветом PAPER. Образ стрелки и значения байтов двух масок приведены на рисунке
Набор программы был выполнен нами при помощи ассемблера ZEUS. Для тех, кто хочет без лишних хлопот с ассемблером получить готовую программу, приводим шестнадцатеричный дамп (с контрольными суммами) кодового блока с адреса 40000. Его длина 328 байтов.
Теперь несколько слов тем, кто захочет усовершенствовать программу. Приведенный вариант программы работает только от KEMPS TON-джойстика (см. строку 1440). Это может оказаться не для всех удобно. Поэтому со своей стороны мы можем порекомендовать ввести дополнительные строки для опроса клавишей, например, SINCLAIR-джойстика, сохранив и KEMPSTON.
|
9C40 |
FB |
C3 |
27 |
9D |
00 |
00 |
00 |
00 |
5E |
|
9C48 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
E4 |
|
9C50 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
EC |
|
9C58 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
F4 |
|
9C60 |
00 |
00 |
00 |
00 |
00 |
00 |
C0 |
E0 |
9C |
|
9C68 |
F0 |
F8 |
FC |
FE |
FF |
FE |
FC |
1C |
FB |
|
9C70 |
0E |
0E |
07 |
07 |
03 |
C0 |
A0 |
90 |
29 |
|
9C78 |
88 |
84 |
82 |
81 |
86 |
B4 |
14 |
0A |
7B |
|
9C80 |
0A |
05 |
05 |
03 |
2A |
64 |
9C |
4C |
A9 |
|
9C88 |
45 |
78 |
CD |
B1 |
22 |
22 |
62 |
9C |
A1 |
|
9C90 |
11 |
44 |
9C |
06 |
0F |
E5 |
0E |
02 |
27 |
|
9C98 |
7E |
12 |
2C |
13 |
0D |
20 |
F9 |
E1 |
0A |
|
9CA0 |
CD |
A6 |
9C |
10 |
F0 |
C9 |
24 |
7C |
B4 |
|
9CA8 |
E6 |
07 |
C0 |
7C |
D6 |
08 |
67 |
7D |
2F |
|
9CB0 |
C6 |
20 |
6F |
D0 |
7C |
C6 |
08 |
67 |
22 |
|
9CB8 |
C9 |
21 |
1A |
77 |
22 |
98 |
9C |
CD |
F2 |
|
9CC0 |
84 |
9C |
21 |
7E |
12 |
22 |
98 |
9C |
83 |
|
9CC8 |
C9 |
3A |
65 |
9C |
E6 |
07 |
08 |
DD |
3A |
|
9CD0 |
21 |
66 |
9C |
CD |
F6 |
9C |
DD |
21 |
EC |
|
9CD8 |
0E |
9D |
DD |
36 |
00 |
AA |
DD |
36 |
EF |
|
9CE0 |
09 |
AB |
DD |
E5 |
DD |
21 |
75 |
9C |
01 |
|
9CE8 |
CD |
F6 |
9C |
DD |
E1 |
DD |
36 |
00 |
B4 |
|
9CF0 |
B2 |
DD |
36 |
09 |
B3 |
C9 |
0E |
0F |
F3 |
|
9CF8 |
2A |
62 |
9C |
50 |
58 |
08 |
47 |
08 |
BB |
|
9D00 |
05 |
04 |
DD |
56 |
00 |
28 |
06 |
CB |
D2 |
|
9D08 |
3A |
CB |
1B |
10 |
FA |
7E |
B2 |
77 |
76 |
|
9D10 |
2C |
7D |
E6 |
1F |
28 |
03 |
7E |
B3 |
B7 |
|
9D18 |
77 |
2D |
DD |
23 |
CD |
A6 |
9C |
7C |
E4 |
|
9D20 |
FE |
58 |
D0 |
0D |
20 |
D5 |
C9 |
21 |
CF |
|
9D28 |
64 |
64 |
22 |
64 |
9C |
DD |
E5 |
CD |
3E |
|
9D30 |
84 |
9C |
CD |
C9 |
9C |
76 |
DB |
1F |
8F |
|
9D38 |
F5 |
CD |
B9 |
9C |
F1 |
4F |
1E |
02 |
4C |
|
9D40 |
16 |
FE |
21 |
65 |
9C |
CB |
41 |
C4 |
E3 |
|
9D48 |
62 |
9D |
CB |
49 |
C4 |
6C |
9D |
16 |
DB |
|
9D50 |
BE |
2B |
CB |
51 |
C4 |
62 |
9D |
CB |
80 |
|
9D58 |
59 |
C4 |
6C |
9D |
CB |
61 |
20 |
16 |
7D |
|
9D60 |
18 |
CD |
7E |
43 |
BA |
28 |
03 |
3C |
C4 |
|
9D68 |
10 |
FA |
77 |
C9 |
7E |
43 |
A7 |
28 |
DF |
|
9D70 |
F9 |
3D |
10 |
FA |
77 |
C9 |
2A |
62 |
19 |
|
9D78 |
9C |
E5 |
7C |
E6 |
18 |
0F |
0F |
0F |
3D |
|
9D80 |
F6 |
58 |
47 |
4D |
E1 |
DD |
E1 |
C9 |
67 |
Другим, более изощренным моментом является изменяемая скорость перемещения стрелки
по экрану. Эти строки мы адресуем тем, кто захочет использовать предложенный интерфейс в серьёзной программе, претендующей на повышенное удобство для пользователя. Как Вы видите из приведенного листинга, скорость перемещения стрелки постоянна и зависит от значения, заданного в строке 330. Слишком быстрая скорость перемещения стрелки приведёт к необходимости более точно "прицеливаться" для попадания в нужное место и к более быстрой реакции Вашей руки, но, в то же время, не потребуется много времени для того, чтобы "перегнать" стрелку от одного края экрана к другому. При медленном перемещении всё наоборот. Великолепная точность попадания и удобство "прицеливания" сочетаются с томительным ожиданием, когда же, наконец, заветная фигурка доползет до нужного поля меню, находящегося почему-то как раз в противоположном конце экрана.
Проблему можно решить следующим образом. Организуется цикл подсчёта количества прерываний, произошедших с момента нажатия любой клавиши перемещения джойстика до её отпускания. При этом начальная скорость перемещения стрелки - минимальна. Если, скажем, через 64 или 32 прерывания кнопка не отпущена, изменяется параметр, задающий скорость перемещения стрелки - её движение убыстряется. Как только кнопка отпущена - счётчик тут же обнуляется и восстанавливается начальное значение параметра, определяющего скорость. Можно ограничиться одной ступенью увеличения скорости, а можно продолжать отсчёт дальше. Если ещё через 32 цикла кнопка не отпущена - скорость увеличивается ещё больше (в одной из версий ART STUDIO, например, увеличение скорости четырехступенчатое - управление при этом очень удобно). Это, так называемое интеллектуальное управление. Конечно, все числовые параметры должны быть тщательно подобраны и сбалансированы для обеспечения максимального удобства управления.
Применение прерываний 2-го рода для создания резидентных процедур всегда представляет особенную трудность для тех, кто делает только первые шаги в машинном коде. Мастерское же владение этим инструментом открывает перед программистом огромные возможности для создания собственных программ. Мы довольно редко получаем письма от наших читателей, в которых есть примеры подобных процедур, да и те далеко не всегда выдерживают наше тестирование. Поэтому мы особенно рады предложить нашим читателям работу, выполненную сотрудником Крымской Астрофизической Обсерватории. Программа прошла тестирование без проблем.