© Иван Рощин, Москва
| ZXNet | : 500:95/462.53 |
| : bestview@mtu-net.ru | |
| WWW | : http://www.ivr.da.ru |
Дата последнего редактирования: 17.03.2003.
Известно, что пересылка содержимого экранной памяти (#1800 байтов) занимает больше времени, чем промежуток между двумя прерываниями. Тем не менее, если изображение должно изменяться не каждые 1/50 секунды, а хотя бы каждые 1/25 секунды, есть способ так выполнить пересылку, что пока луч рисует текущий кадр мы видим первую картинку; когда луч рисует следующий кадр мы видим уже вторую картинку.
Рассмотрим, в чём заключается этот способ. Пусть в видеопамяти (#4000#5800) находится первая картинка. После прихода импульса прерывания луч начинает рисовать изображение, начиная с верхнего края экрана, рисует бордюр и в конце концов прорисовывает самую верхнюю строку малого экрана.
+--------------------+ \ | Бордюр | | | +--------------+ | | | | | | | | | Малый экран | | | Телевизионный экран | | | | | | +--------------+ | | | | | +--------------------+ / |
Вот
Переброска картинки продолжается до того, как луч прорисует весь экран. Посчитаем, сколько это займёт времени: весь экран 320 строк, верхняя часть бордюра 80 строк, и ещё одну строку мы специально пропустили. Т.к. время прорисовки одной строки 224 такта, получаем (32081)*224=53536 тактов. За это время, конечно, полностью обновить видеопамять не получится, но это пока и не нужно.
После того, как луч прорисует весь экран, поступит следующий импульс прерывания, и начнёт прорисовываться следующий кадр. Пока луч рисует верхнюю часть бордюра и верхнюю часть малого экрана (т.е. уже вторую картинку), мы, не теряя времени, перебрасываем в видеопамять оставшуюся часть второй картинки. Переброска должна быть завершена до того момента, как луч начнёт рисовать нижнюю строку малого экрана, т.е. процедура переброски должна укладываться в 53536+(80+1921)*224=114240 тактов. А этого с избытком хватит даже для переброски картинки вместе с атрибутами (в этом случае процедура должна пересылать по очереди 8 линий картинки и атрибуты для этих 8 линий).
Это расчёты для
А теперь две программы, выполняющие одну и ту же задачу: каждые 1/25 секунды они меняют цвет экрана с белого на чёрный и наоборот. Первая программа использует LDIR, а вторая работает по рассмотренному выше алгоритму. Почувствуйте разницу!
Программа 1:
LD HL,#8000 ;1-я картинка.
LD (HL),0
LD DE,#8001
LD BC,#17FF
LDIR
LD HL,#9800 ;2-я картинка.
LD (HL),#FF
LD DE,#9801
LD BC,#17FF
LDIR
L1 HALT
LD HL,#8000
LD DE,#4000
LD BC,#1800
LDIR
HALT
LD HL,#9800
LD DE,#4000
LD BC,#1800
LDIR
XOR A
IN A,(254)
CPL
AND 31
JR Z,L1
RET
Программа 2:
PIC1 EQU #8000 ;1-я картинка.
PIC2 EQU #9800 ;2-я картинка.
LD HL,PIC1
LD (HL),0
LD DE,PIC1+1
LD BC,#17FF
LDIR
LD HL,PIC2
LD (HL),#FF
LD DE,PIC2+1
LD BC,#17FF
LDIR
;Строим таблички с адресами переброски:
LD BC,PIC1-#4000
LD HL,TABL1
LD DE,#4000
CALL MAKE_T
LD BC,PIC2-#4000
LD HL,TABL2
LD DE,#4000
CALL MAKE_T
;Главный цикл программы:
LOOP1 LD HL,TABL1
LD DE,BUFER+100
LD BC,192*4
LDIR
CALL MOVER
LD HL,TABL2
LD DE,BUFER+100
LD BC,192*4
LDIR
CALL MOVER
XOR A
IN A,(254)
CPL
AND 31
JR Z,LOOP1
;---------------------------------------
;Процедура MOVER непосредственно
;выполняет пересылку:
MOVER HALT
;Чтобы не было задержек на обработку
;прерывания, можно поставить здесь DI
;(тогда при выходе из этой процедуры
;нужно поставить EI)
LD (QUIT+1),SP
LD SP,BUFER+100
;Задержка, пока не прорисуется 1-я строка:
LD HL,0
LD DE,0
LD BC,#330
LDIR
LD BC,#1800
;Берём со стека новые значения HL и DE,
;указывающие на следующую строку:
MMMM POP DE
POP HL
TO_LDI LDI:LDI:LDI:LDI:LDI:LDI:LDI:LDI
LDI:LDI:LDI:LDI:LDI:LDI:LDI:LDI
LDI:LDI:LDI:LDI:LDI:LDI:LDI:LDI
LDI:LDI:LDI:LDI:LDI:LDI:LDI:LDI
JP PE,MMMM ;Продолжаем...
QUIT LD SP,0
RET
;---------------------------------------
;Процедура MAKE_T строит табличку:
MAKE_T LD A,D
CP #58
RET Z
LD (HL),E
INC HL
LD (HL),D
INC HL
EX DE,HL
ADD HL,BC
EX DE,HL
LD (HL),E
INC HL
LD (HL),D
INC HL
EX DE,HL
AND A
SBC HL,BC
EX DE,HL
INC D
LD A,D
AND 7
JR NZ,MAKE_T
LD A,E
SUB #E0
LD E,A
JR NC,MAKE_T
LD A,D
SUB 8
LD D,A
JR MAKE_T
;---------------------------------------
TABL1 DS 192*4
TABL2 DS 192*4
;Стек для процедуры
;обработки прерываний (если во время
;работы проц. MOVER прерывания
;запрещены, он не нужен):
BUFER DS 100
;"Одноразовая" табличка адресов строк
;(разрушается процедурой обработки
;прерываний и нуждается в обновлении):
DS 192*4