А теперь - несколько полезных
советов любителям музыкальных
DEMO:
EYE ACHE 2 - если во время
подгрузки с диска музыка начи-
нает тормозить, попробуйте пере-
писать программу на диск с че-
редованием секторов = 1 (обяза-
тельно в начало диска!)
RAGE - если при запуске удер-
живать нажатой клавишу SPACE
(или запустить программу в режи-
ме 48K), можно прочитать интере-
сный текст, в котором содержится
несколько советов начинающим де-
момейкерам.
* * *
(c) Иван Рощин, Москва, 1997
Быстрая переброска экрана
Известно, что пересылка со-
держимого экранной памяти (#1800
байтов) занимает больше времени,
чем промежуток между двумя пре-
рываниями. Тем не менее, если
изображение должно изменяться не
каждые 1/50 секунды, а хотя бы
каждые 1/25 секунды, есть способ
так выполнить пересылку, что по-
ка луч рисует текущий кадр - мы
видим первую картинку; когда луч
рисует следующий кадр - мы видим
уже вторую картинку.
Рассмотрим, в чем заключается
этот способ. Пусть в видеопамяти
(#4000-#5800) находится первая
картинка. После прихода импульса
прерывания луч начинает рисовать
изображение, начиная с верхнего
края экрана, рисует бордюр и в
конце концов прорисовывает самую
верхнюю строку малого экрана.
┌────────────────────┐\
│ бордюр │ │
│ ┌──────────────┐ │ │
│ │ │ │ │
│ │ │ │ │телевизионный
│ │ малый экран │ │ │экран
│ │ │ │ │
│ │ │ │ │
│ └──────────────┘ │ │
│ │ │
└────────────────────┘/
Вот тут-то мы и начинаем пе-
ребрасывать вторую картинку из
буфера в видеопамять, строго в
том же порядке, как она изобра-
жается на экране (т.е. по лини-
ям, сверху вниз). Поскольку луч
формирует изображение быстрее,
чем мы обновляем содержимое ви-
деопамяти, на экране будет изоб-
ражена первая картинка.
Переброска картинки продолжа-
ется до того, как луч прорисует
весь экран. Посчитаем, сколько
это займет времени: весь экран -
320 строк, верхняя часть бордю-
ра - 80 строк, и еще одну строку
мы специально пропустили. Т.к.
время прорисовки одной строки -
224 такта, получаем (320-81)*224
=53536 тактов. За это время, ко-
нечно, полностью обновить видео-
память не получится, но это пока
и не нужно.
После того, как луч прорису-
ет весь экран, поступит следую-
щий импульс прерывания, и начнет
прорисовываться следующий кадр.
Пока луч рисует верхнюю часть
бордюра и верхнюю часть малого
экрана (т.е. уже вторую картин-
ку), мы, не теряя времени, пере-
брасываем в видеопамять оставшу-
юся часть второй картинки. Пере-
броска должна быть завершена до
того момента, как луч начнет ри-
совать нижнюю строку малого эк-
рана, т.е. процедура переброски
должна укладываться в 53536+(80+
192-1)*224=114240 тактов. А это-
го с избытком хватит даже для
переброски картинки вместе с ат-
рибутами (в этом случае процеду-
ра должна пересылать по очереди
8 линий картинки и атрибуты для
этих 8 линий).
Это расчеты для "Пентагона-
128". Фирменный Спектрум отлича-
ется от него по следующим пара-
метрам: верхняя часть бордюра
составляет 64 строки вместо 80 и
на экране 312 строк вместо 320.
Чтобы процедура переброски рабо-
тала и на нем, она должна зани-
мать не более (312-81)*224+(64+
191)*224=108864 тактов. Но этого
все равно хватает, даже учиты-
вая, что при записи/чтении ви-
деопамяти ULA тормозит процес-
сор. А вот если процессор, на-
оборот, будет работать быстрее
(турбированный Спектрум), проце-
дура переброски может и не дать
нужного результата. Чтобы она
правильно работала и в этом слу-
чае, нужно, чтобы она "укладыва-
лась в прерывание" и завершала
свою работу до того, как начнет
прорисовываться нижняя линия ма-
лого экрана).
А теперь - две программы, вы-
полняющие одну и ту же задачу:
каждые 1/25 секунды они меняют
цвет экрана с белого на черный и
наоборот. Первая программа ис-
пользует LDIR, а вторая работает
по рассмотренному выше алгорит-
му. Почувствуйте разницу!
Программа 1:
140.
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
* * *