2.2.4 Управление окном от прерываний 2-го рода.
Выше, в разделе 2.1.5 мы рассмотрели процедуру FN h(), предназначенную для управления спрайтами от клавиатуры с использованием прерываний второго рода Как мы только что убедились, "оконная" технология, связанная со скроллингом позволяет в некоторых случаях получать более интересные результаты, чем технология работы со спрайтами. Было бы интересно объединить процедуру, управления от клавиатуры с использованием прерываний второго рода с процедурой скроллирования спрайта в окне, чем мы здесь и займемся на примере процедуры FN о(s,x,y,1,n,d,г).
Эта процедура уже может стать основным приводом (engine) Вашей будущей самостоятельной игры типа Space Raders, в которой Вы управляете движением своей пушки "влево-вправо" и расстреливаете проплывающих над Вами инопланетян. При этом движением (скроллингом) "инопланетян" как бы управляет от прерываний 2-го рода процедура FN о(), а движенчем спрайта "пушки" - процедура FN h( ) .
Параметры процедуры.
s параметр старт/стоп. Поскольку процедура работает от пре рываний 2-го рода, то ее надо не только уметь запустить, но и уметь остановить. Средствами БЕЙСИКа она не остановится. Для этого и введен дополнительный параметр s. При задании s=0 процедура стартует, а при з=1 - останавливается .
х,у - координаты окна. Они задаются для левого верхнего угла окна. Способ задания координат здесь принят в знакоместах.
0<=х<=31; 0<=у<=21
1 - ширина окна (в знакоместах 0... 31) п - номер спрайта, скроллируемого в окне.
d - direction - параметр, определяющий направление перемещения .
d=0 - скроллинг вправо. d=l - скроллинг влево.
г - флаг повтора: г=0 - есть повтор; г=1 - нет повтора.
Листинг 25
Загрузчик машинного кода процедуры скроллирования спрайта в окне с использованием IM2.
10 REM *** Загрузчик машинного кода
20 LET adr=49200: LET long=315: LET check=81594: LET sum=0 30 FOR k=0 TO long-1: READ a 40 POKE (adr+k).a: LET sum=sum+a 50 NEXT k
60 IF sumocheck THEN PRINT "??": STOP 100 REM *** Данные для машинного кода
110 DATA 243,042,011,092,001
120 DATA 004,000,009,126,254
130 DATA 000,032,009,017,252
140 DATA 207,237,083,250,207
150 DATA 251,201,017,139,192
160 DATA 237,083,250,207,014
170 DATA 008,009,086,009,094
180 DATA 009,126,050,100,193
190 DATA 009,126.050,108,193
200 DATA 009,126,230,001,050
|
210 |
DATA |
107 |
,193, |
009, |
126, |
230 |
|
220 |
DATA |
001 |
,050, |
106, |
193, |
062 |
|
230 |
DATA |
001 |
,050, |
104, |
193, |
050 |
|
240 |
DATA |
109 |
,193, |
050, |
101, |
193 |
|
250 |
DATA |
123 |
,230, |
024, |
246, |
064 |
|
260 |
DATA |
103 |
,123, |
230, |
007, |
183 |
|
270 |
DATA |
031 |
,031 , |
031, |
031, |
130 |
|
280 |
DATA |
111 |
,034, |
102, |
193, |
251 |
|
290 |
DATA |
201 |
,058, |
107, |
193, |
254 |
|
300 |
DATA |
000 |
,040, |
006, |
058, |
100 |
|
310 |
DATA |
193 |
,133, |
061 , |
111, |
058 |
|
320 |
DATA |
101 |
,193, |
071 . |
016, |
005 |
|
330 |
DATA |
205 |
,240, |
192, |
006, |
008 |
|
340 |
DATA |
120 |
,050, |
101 , |
193, |
017 |
|
350 |
DATA |
110 |
,193, |
042, |
102, |
193 |
|
360 |
DATA |
058 |
,107, |
193, |
254, |
000 |
|
370 |
DATA |
040 |
,003, |
017, |
152, |
193 |
|
380 |
DATA |
006 |
,003, |
229, |
197, |
120 |
|
390 |
DATA |
254 |
,001, |
032, |
004, |
006 |
|
400 |
DATA |
005 |
,024, |
002, |
006, |
008 |
|
410 |
DATA |
197 |
,213, |
229, |
058, |
107 |
|
420 |
DATA |
193 |
,254, |
000, |
032, |
005 |
|
430 |
DATA |
205 |
,042, |
193, |
024, |
003 |
|
440 |
DATA |
205 |
,071 , |
193, |
225, |
209 |
|
450 |
DATA |
193 |
,036, |
019, |
016, |
231 |
|
460 |
DATA |
193 |
,225, |
062, |
032, |
133 |
|
470 |
DATA |
111 |
,048, |
004, |
062, |
008 |
|
480 |
DATA |
132 |
,103, |
016, |
204, |
195 |
|
490 |
DATA |
252 |
,207, |
058, |
109, |
193 |
|
500 |
DATA |
061 |
,050, |
109, |
193, |
192 |
|
510 |
DATA |
062 |
,003, |
050, |
109, |
193 |
|
520 |
DATA |
058 |
,108, |
193, |
017 > |
063 |
|
530 |
DATA |
000 |
,071 , |
033, |
072, |
213 |
|
540 |
DATA |
167 |
,237, |
082, |
025, |
016 |
|
550 |
DATA |
253, |
067, |
017, |
110, |
193 |
|
560 |
DATA |
058, |
104, |
193, |
254, |
000 |
|
570 |
DATA |
040, |
001, |
126, |
018, |
035 |
|
580 |
DATA |
019, |
016, |
243, |
058, |
106 |
|
590 |
DATA |
193, |
254, |
000, |
200, |
062 |
|
600 |
DATA |
000, |
050, |
104, |
193, |
201 |
|
610 |
DATA |
167, |
006, |
003, |
213, |
026 |
|
620 |
DATA |
031, |
018, |
245, |
062, |
021 |
|
630 |
DATA |
131 , |
095, |
048, |
001 , |
020 |
|
640 |
DATA |
241, |
016, |
242, |
209, |
058 |
|
650 |
DATA |
100, |
193, |
071, |
203, |
030 |
|
660 |
DATA |
035, |
016, |
251, |
201, |
167 |
|
670 |
DATA |
213, |
006, |
003, |
026, |
023 |
|
680 |
DATA |
018, |
245, |
123, |
214, |
021 |
|
690 |
DATA |
095, |
048, |
001 , |
021, |
241 |
|
700 |
DATA |
016, |
242, |
209, |
058, |
100 |
|
710 |
DATA |
193, |
071, |
203, |
022, |
043 |
|
720 |
DATA |
016, |
251 , |
201 , |
005, |
004 |
|
730 |
DATA |
000, |
000, |
000, |
000, |
000 |
Листинг 26
Дисассемблер процедуры, управляющей скроллингом спрайта в окне при использовании прерываний 2-го рода.
Адрес Маш.код Метка Мнемоника
Комментарий
СОЗО F3 С031 2А0В5С
С034 010400 С037 09
DI LD
HL,(#5С0В)
LD ВС,#0004 ADD HL,BC
;Отключение прерываний. ;Указание на адрес, в ;котором располагаются ;параметры функции пользователя FN п(). ;Вычисление адреса первого параметра.
Адрес Маш-код Метка Мнемоника
Комментарий.
СО3D 11FCCF
LD
CP OR LD LD
EI RET
С040 ED53FACF
С044 FB С045 С9
A,(HL.) ;Проверка параметра
#00 ;s.
NZ,START ;Еслн не 0, то стартуем DE,#CFFC ;Иначе надо прекратить (#CFFA),DE обработку прерываний ;2-го рода. Оформляем ;выход из процедуры ;FN h() - см.с. 56. ;Разрешение прерываний .Возврат.
C04D 0Е08 C04F 09
С050 С051
С052 5Е С053 09
СО 54 7Е С055 3264С1
С05А 326СС1
56 09
DE,IM2 (#CFFA),DE
C, #08 HL.BC
D.(HL) HL.BC
LD LD
LD E,(HL) ADD HL.BC
A, (HL) (WIDTH) ,A
ADD HL.BC
LD A.(HL)
LD (NUMBER),A
ADD HL,ВС
LD A,(HL)
С046 118ВС0 START LD С049 ED53FACF LD
LD ADD LD ADD
.Включение процедуры. .В процедуре FN h( ) ; выставляется новый .адрес для обработки прерываний 2-го рода ;Переход ко 2-му пара-,метру.
;Прием параметра х ;Переход к 3-му пара-,метру.
;Приен параметра у. ; Переход к 4-му параметру.
;Прием параметра 1. ;Сохранили ширину окна ,в программной переменной .
;Переход к 5 му пара-,метру.
;Прием параметра п. Сохранили в переменной ; Переход к 6-му пара-;метру.
;Прием параметра d
C05F £601
С061 326ВС1 С064 09
С065 7Е С066 Е601
326АС1
ЗЕ01
С068 С06В C06D
3268С1
С070 326DC1
СО 73 3265С1
LD (DIREC).A
LD A,(HL)
Адрес Маш-код Метка Мнемоника
LD LD LD
(REPIT),A A,#01 (FLAG),A
LD (COUNT),A
LD (COUNT8),A ;Маскирование старших ;битов.
;Сохранили в переменной. ;Переход к 7-му пара ;метру.
;Прием параметра г. ;Маскирование старших ;битов
;Сохранили в переменной.
инициализация флаговой Переменной. Инициализация троичного счетчика. Инициализация восьмеричного счетчика.
Комментарий.
LD AND OR LD LD AND OR RRA RRA RRA RRA
СО 7 6 С077 С079 С07В С07С C07D C07F С080 С081 С082 С083 С084 С085
7В
Е618
F640
67
7В
Е607 В7 1F 1F 1F 1F 82 6F
A, E #18 #40 H,A A, E #07 A
ADD A,D
LD
L, A
Поиск в дисплейном файле адреса, соответствующего коор динатам, заданным знакоместах-
Адрес выставляется в регистровой паре HL
LD (SCRAD) , HL
EI RET ;Сохранили его в про ;граммной переменной. ;Разрешение прерываний. ;Возврат
С086 2266С1
С089 FB С08А С9
Резидентная процедура, обрабатывающая прерывания 2-го рода. Мы попадаем сюда из процедуры Fn h(), см с.56, поскольку операцией #С049 там был выставлен именно этот адрес.
Адрес Маш.код Метка Мнемоника
COBB ЗА6ВС1 IM2 LD A,(DIREC) ;Направление^скроллинга.
С08Е FEOO CP #00 ;Проверка направления.
С090 2806 3R Z.LBL-1 :Если вправо, то переход
С092 ЗА64С1 LD A,(WIDTH) .Ширина окна.
С095 85 ADD A,L Получили х+1
С096 3D DEC А ;Получили х+1-1.
С097 6F LD L,A ;что равно координате х
последнего (правого) .столбца окна. Если ;скроллинг идет влево, ;то эта координата нужна ;как исходная. ;Проверка восьмиразрядного счетчика, ;Выставляется как параметр цикла.
;Элегантный пример того, ;как инструкция D3NZ используется не для организации цикла, а для .организации периодического ветвления. ;Прием спрайта в буфер. ;Установка значения в восьмиразрядном счет ;чике.
;Адрес в буфере, указывающий на начало левого ;столбца спрайта. СОАА 2А66С1 LD HL,(SCRADD) .Экранный адрес
COAD ЗА6ВС1 LD A,(DIREC) Направление скроллинга.
Комментарий
С098 ЗА65С1
LBL-1 LD А,(COUNT8) LD В, А D3NZ BRANCH
С09В 47
С09С 1005
С09Е С0А1 СОАЗ С0А4 С0А7
CDF0C0 0608 78
3265С1 116ЕС1
CALL GETSPR LD В,#08 BRANCH LD А,В
LD (COUNT8),А LD DE.BUFFER
Адрес Наш.код Метка Мнемоника
Комментарий
СОВО FE00 С0В2 2803
С0С6 С0С7 С0С8 С0С9 СОСС СО СЕ C0D0
СОВ4 1198С1
С0В7 0603
С0В9 Е5 СОВА С5
СОВВ 78 СОВС FE01 СОВЕ 2004
COCO 0605
С0С2 1802 С0С4 0608
C5 D5 E5
3A6BC1 FEOO 2005 CD2AC1
C0D3 1803 C0D5 CD47C1
C0D8 El C0D4 D1
CP #00 OR Z,LBL-2
LD DE,#C198
LBL-2 LD B,#03
LOOP-l PUSH HL PUSH ВС
LD А,В CP #01
OR NZ,LBL-3
OR
LD
LBL-4
LBL-5
LD B,#05
LOOP-2 В, #08
LBL-3
LOOP-2
PUSH ВС PUSH DE PUSH HL LD A,(DIREC) CP #00 OR NZ.LBL-4 CALL RIGHT
OR LBL-5 CALL LEFT
POP HL POP DE
;Вправо?
;Если движение вправо, ; то обход следующей опе-;рации.
.Адрес, с которого в буфере начинается правый ;столбец спрайта. ;Цикл по трем вертикаль-;ным рядам спрайта. ;Сохранение регистров на ;стеке перед организацией ;цикла
;Проверка, с каким рядом :мы имеем дело. ;Если не с последним, ;то обход следующей ;операции.
;В последнем ряду спрайта только пять линий, ,Обход.
;В двух верхних рядах ;спрайта по восемь ли ;ний. Это организация ;счетчика очередного .цикла.
Направление скроллинга.
.Если влево, то обход :Вызов процедуры ;скроллинга вправо. ;Обход.
;Вызов процедуры Скроллинга влево. ;Восстановление регистров :со стека перед оконча
АНИМАЦИЯ В РАСТРОВОЙ ГРАФИКЕ _Комментарий.
Адрес Маш.код Метка Мнемоника
POP ВС INC Н
D3NZ LOOP-2
LD A, #20
С0Е1 СОЕЗ С0Е4 С0Е5
ЗЕ20 85 6F 3004
3R NC,LBL-6
С0Е7 ЗЕ08 СОЕ9 84 • СОЕА 67
СОЕВ 10СС LBL-6 COED C3FCCF
LD A, #08 ADD A,H LD H,A
D3NZ LOOP-1 3P #CFFC
,нием цикла.
;Переход к соседней сциэу ;линии знакоместа на зк-гране .
;Переход к соседней снизу ;линии в шаблоне спрайта. ;Конец цикла. ;Восстановление регистров ;со стека перед окончанием цикла.
;Переход к соседнему сни-;зу знакоместу на экране.
;Если не произошло переполнение регистра L, то ;обход следующих опера ;ций.
;Если же такое переполнение произошло, то это ;означает, что мы вошли ;в новый экранный сегмент ;и регистр Н увеличивается на 8 пунктов. ;Конец цикла. ;Выход через процедуру ;Fn h(), см.с.56.
Процедура GETSPR.
(COUNT),A NZ
C0F0 3A6DC1 GETSPR LD A,(COUNT)
C0F3 C0F4 C0F?
3D
326DC1 СО
DEC
LD
RET
;Приняли данные из ;троичного счетчика. ;Сняли с него единицу. ,И снова его запомнили ;Если не ноль, значит
Адрес Маш-код Нетка Мнемоника
Комментарий.
C0F8 ЗЕОЗ
COFA 326DC1
COFD ЗА6СС1
С100 113F00
С103 47
С104 2148D5
С107 А7
С108 ED52 С10А 19
С10В 10FD
C10D 43 С10Е 116ЕС1
CI 14 FEOO C110 2801
LD А,#03
LD (COUNT),А
LD A,(NUMBER)
LD DE,#D03F
LD В,A
LD HL,#D548
AND A
SBC HL,DE NEXT ADD HL,DE
D3NZ NEXT
ClJl 3A68C1 AGAIN LD A,(FLAG)
#00
Z,BYPASS
CP OR
LD B,E LD DE,BUFFER
наш спрайт еще не весь "выехал" на зкран и при нимать спрайт в буфер пока не надо. Выставляем число 3 в троичном счетчике. Номер спрайта. Длина шаблона одного спрайта.
Создали счетчик. Адрес начала таблицы, в которой размещаются спрайты (54600). Сброс флага переноса, чтобы он не влиял на результат операции SBC. Выставление начального адреса для первого спрайта
Возврат за отысканием адреса очередного спрайта.
Длина шаблона спрайта. Приняли адрес временного буфера для размещения спрайта
Проверка флага, связан ного с необходимостью повторного "прогона" спрайта
Проверка па ноль. Если ноль, то спрайт принимать не надо, идем в обход и обнуляем б) фер.
Адрес Маш.код Метка Мнемоника
Комментарий
C11A 23
С11В 13
С11С 10F3
C11E 3A6AC1
C126 3268C1
INC HL
INC DE
DJNZ AGAIN
LD A,(REPIT)
CP #00
RET Z
LD A, #00
LD (FLAG),A RET
С116 7Е LD A,(HL)
С119 12 BYPASS LD (DE),А
;Байт шаблона спрайта. ;Запомнили его в буфере ;Переход к очередному ;байту шаблона. .Переход к очередному ;байту буфера. ;Если не все байты шабло ;на скопированы, то возврат
;Проверка необходиимости ;повтора.
;Если есть необходимость ;то выход, в переменной ;FLAG остается единица. ;В противном случае обнуляем переменную FLAG. ;Возврат в вызывающую ;процедуру,
Процедура RIGHT.
С12А А7 RIGHT AND А
С12В 0603 LD В,#03
PUSH DE
C12F IF
С130 12 С131 F5
C12D D5
C12E 1A LOOP-ЗА LD A,(DE)
RRA
LD (DE),A PUSH AF
;Сброс флага переноса. ;Начало внутреннего ;цикла. Установка ;параметра цикла. ;Сохранение регистра ;на время работы подпро-;граммы.
;Взяли в аккумулятор ;байт иэ левого вертикального столбца в шаблоне спрайта. .•Ротация вправо. ;Заменили байт в шаблоне ;Сохранили флаговый ре-
Адрес Маш-код Метка Мнемоника
Комментарий -
C13D ЗА64С1
C143 23
C144 10FB
C146 C9
OR NC,LBL-7
C141 CB1E LOOP-4A RR (HL)
INC HL
D3NZ LOOP-4A
RET
LBL-7 POP AF
DJNZ LOOP-ЗА POP DE
LD A, (WIDTH) LD B,A
;гистр на стеке. Важен ;флаг переноса. ; Сдвиг на 21 байт для ;перехода к соседнему ;справа столбцу. .Указатель в буфере ;спрайта переместили. ;Если не возникло пе ;реполнения, то обход. ;Иначе наращиваем ;старший регистр, восстановили флаг С. ;Конец цикла, восстановили указатель ;на буфер. ;Ширина окна. ;Ввели ее в качестве ;счетчика.
;Ротация вправо байтов ;в окне.
;Переход в окне к соседнему знакоместу справа. ;Прокручиваем линию по ;всей ширине окна. ;Возврат в вызывающую ; процедуру
Процедура LEFT.
С147 А 7 LEFT
AND А
PUSH DE
LD В,#03
С148 D5
С149 0603 ;Сброс флага переноса ;Сохранение регистра ;на время работы подпро ;граммы.
;Начало внутреннего
Адрес Маш коп Метка мнемоника
Комментарий
C15A 3A64C1
C161 10FB
C163 C9
OR NC.LBL 8
D3NZ LOOP-3B
LD A, (WIDTH)
С14В 1А LOOP-ЗВ LD А,(DE)
С14С 17 RLA
C14D 12 LD (DE),A
С14Е F5 PUSH AF
C15E CB16 LOOP-4B RL (HL) CI 60 2B DEC HL
D3NZ LOOP-4B
RET
:цикла. Установка параметра цикла ;Взяли в аккумулятор ;байт из правого вертикального столбца в шаблоне спрайта. ;Ротация влево. ;Заменили байт в шаблоне.
.•Сохранили флаговый регистр на стеке. Важен ;флаг переноса. ;Сдвиг назад на 21 байт ;для перехода к соседнему ;слева столбцу. ;Если не возникло двоичного займа, то обход. .Уменьшаем старший байт восстановили флаг С. .Конец внутреннего цикла, восстановили указатель ;на буфер. ;Ширина окна. ;Ввели ее в качестве ;счетчика.
.Ротация влево байтов :в окне.
;Переход к соседнему .знакоместу слева. ;Прогон на всю ширину .окна.
;Возврат в вызывающую ;процедуру.
ДВИЖЕНИЕ СПРАЙТА В ОКНЕ
135
Комментарий.
Адрес Маш.код Метка Мнемоиика
DEFB #05 DEFB #00 DEFW #0000 DEFB #00
NOP
DEFB #00 DEFB #00 DEFB #00 DEFB #00
С164 С165 С166 С168
WIDTH
C0UNT8
SCRAD
FLAG
05 04 00 00
С169 С16А С16В С16С C16D
00 00 00 00 00
REPIT DIREC NUMBER COUNT
C16E 0000 . BUFFER DEFM #0000
.Ширина окна. ;Восьмеричный счетчик. ;Экранные координаты ;Флаг, указывающий на необходимость повтора ;"прогона" спрайта.
;Параметр повтора. Направление скроллинга Помер спрайта ;Троичный счетчик для процедуры GETSPR. :Буфер для временного ;хранения шаблона ;спрайта.