ZX Forum #04
19 ноября 1997

Мир звуков Спектрума - глава 4.9: воспроизведение звука на прерываниях.

<b>Мир звуков Спектрума</b> - глава 4.9: воспроизведение звука на прерываниях.
         4.9. Звук на прерываниях

   У всех подпрограмм, приведенных в  пре-
дыдущих главах, есть один  общий  недоста-
ток: на время их звучания  выполнение  ос-
новной программы  приостанавливается.  Это
можно исправить, хотя и  с трудом, исполь-
зуя второй режим прерываний.  Те, кто зна-
ет, что это такое, могут смело  пропустить 
следующие несколько абзацев.
   Как  уже  говорилось  раньше, пятьдесят
раз в секунду процессор получает сигнал  о
необходимости вызова прерывания. При  этом
он вызывает  некоторую подпрограмму, после
чего продолжает обрабатывать основную про-
грамму.
   Существует три различных режима  преры-
ваний: 0, 1 и 2, которые выбираются коман-
дами IM 0, IM 1 и IM 2. Стандартный  режим
имеет номер 1. О нем уже было рассказано в
главе 3, но  на всякий случай напомню, что
в этом режиме в качестве обработчика  пре-
рываний используется подпрограмма  ПЗУ  по
адресу 56 (#38), которая следит за клавиа-
турой и счетчиком времени. Режим 0 нам  не
интересен, так как в ZX-Spectrum он анало-
гичен режиму 1. А вот режим 2 и  есть  са-
мое интересное!
   Во втором режиме  прерываний  пятьдесят
раз в секунду происходит  следующее:  мик-
ропроцессор считывает с шины данных  байт,
называемый вектором прерывания.  Он  пере-
дается  в младший байт  шины  адреса, а  в
старший байт записывается  содержимое  ре-
гистра I. По полученному таким образом ад-
ресу процессор  считывает  из  памяти  два
байта, которые интерпретируются как  адрес
подпрограммы обработки прерывания.
   ZX-Spectrum  устроен  так,  что  вектор
прерывания обычно равен 255 (#FF), но  не-
которые внешние устройства, например, AMX-
mouse, могут  генерировать  другие  векто-
ра. Кроме того, в некоторых некачественных
спектрумах вектор прерывания  может  изме-
няться абсолютно случайным образом.
   Исходя  из всего  вышесказанного, можно
предложить  следующую   последовательность
действий для  установки  собственной  под-
программы обработки прерываний:

   1. Запретить прерывания.
   2. Записать в память адрес  обработчика
прерываний.
   3. Задать в регистре I старший байт ад-
реса указателя на обработчик.
   4. Установить второй режим прерываний.
   5. Разрешить прерывания.

   А для возврата  к  стандартному  режиму
обработки прерываний нужно выполнить такие
действия:

   1. Запретить прерывания.
   2. Записать в регистр I число 63.
   3. Установить первый режим прерываний.
   4. Разрешить прерывания.

   Так как вектор прерывания  может  изме-
няться, вместо записи двух байтов по опре-
деленному адресу выстраивается целая  таб-
лица размером 257 байт с  таким  расчетом,
чтобы при любом значении вектора считывал-
ся один и тот же адрес.  Понятно, что  для
этого все байты таблицы должны быть одина-
ковыми.
   При составлении процедур обработки пре-
рываний следует  придерживаться  некоторых
правил.  Во-первых, обработчик  прерывания
должен выполняться за достаточно  короткий
промежуток времени. Во-вторых, все  регис-
тры,  используемые  в  обработчике,  перед
возвратом должны принять  значения,  нахо-
дившиеся в них  до  вызова  прерывания.  В
связи с этим не рекомендуется обращаться к
подпрограммам ПЗУ, по крайней мере до  тех
пор, пока Вы не знаете  совершенно  точно,
какие в них используются регистры и  какие
системные переменные при этом  могут  быть
изменены. Вызов подпрограмм ПЗУ не желате-
лен еще  и потому, что  некоторые  из  них
разрешают  прерывания, что  совершенно  не
допустимо во избежание вызова  обработчика
из самого себя.  Любой  обработчик  должен
работать  при  запрещенных    прерываниях.
Однако использовать  команду  DI  в  самом
начале процедуры  не обязательно, так  как
это делается автоматически и Вам надо  по-
заботиться только о разрешении  прерываний
перед выходом.
   Если Вы не хотите  лишаться  возможнос-
тей, предоставляемых стандартным  обработ-
чиком  прерываний, можете  использовать  в
своей подпрограмме команду RST 56.  А  при
использовании прерываний в бейсик-програм-
мах  это  просто  необходимо, иначе  будет
заблокирована клавиатура.
   Теперь разберемся, чем нам  могут  быть
полезны прерывания.
   Если  задать  некоторую  последователь-
ность звуков и в  каждом  прерывании  вос-
производить короткую ее часть, то получит-
ся довольно хороший эффект параллельного с
программой звука. Причем каждая часть дол-
жна  быть  действительно  очень  короткой,
иначе толку от прерываний не будет.
   Условимся, что последовательность  зву-
ков будем задавать блоком данных в следую-
щем  формате:  для  каждой  ноты  в  блоке
данных должно быть по  два  байта.  Первый
байт - частота (1...253), а второй байт  -
длительность (0...255). Кроме того,  могут
встречаться такие контрольные коды:

     0 - переключение тон/шум
   254 - начало цикла
   255 - конец блока

   Изначально программа настроена  на  вы-
вод чистого тона, но, если Вам  необходимо
получить  шум, Вы  можете  переключить  ее
на воспроизведение шума, вставив  в данные
байт, равный 0. Для повторного  переключе-
ния на тон байт 0 должен  встретиться  еще
раз.
   Когда программа встретит байт  255, вы-
вод звука либо прекратится, либо вся  пос-
ледовательность повторится снова - в зави-
симости от заданного числа повторений.
   Если в блоке данных встретится код 254,
то при очередном повторении эффект начнет-
ся не  с начала, а с места, где  этот  код
встретился.
   Теперь сама программа. Она является за-
конченным комплексом и может быть  оттран-
слирована ассемблером без малейших измене-
ний:
1415.
  10           ORG     60000
  20           JP      SINIT      ; подключение прерываний
  30           JP      SSTOP      ; отключение прерываний
  40           JP      NEWFX      ; инициализация эффекта
  50  MUTE     LD      (COUNT),A  ; "заглушка"
  60           RET
  70  SINIT    XOR     A
  80           LD      (COUNT),A
  90           LD      A,24       ; код команды JR
 100           LD      (65535),A
 110           LD      A,195      ; код команды JP
 120           LD      (65524),A
 130           LD      HL,INTR    ; HL=адрес обработчика
 140           LD      (65525),HL
 150           LD      HL,65024
 160           LD      DE,65025
 170           LD      BC,256
 180           LD      (HL),255   ; адрес прерывания - 65535
 190           LD      A,H
 200           LDIR               ; заполнение таблицы
 210           DI
 220           LD      I,A
 230           IM      2
 240           EI
 250           RET
 260  SSTOP    DI                 ; отключение прерываний
 270           LD      A,63
 280           LD      I,A
 290           IM      1
 300           EI
 310           RET
 320  NEWFX    DI                 ; инициализация эффекта
 330           LD      (COUNT),A
 340           XOR     A
 350           LD      (FLAG),A
 360           LD      (ADDR),HL
 370           LD      (CURADD),HL
 380           EI
 390           RET
 400  ADDR     DEFW    0          ; начальный адрес блока данных
 410  CURADD   DEFW    0          ; текущий адрес в блоке данных
 420  COUNT    DEFB    0          ; количество повторений
 430  FLAG     DEFB    0          ; флаг тон/шум
 440  INTR     PUSH    AF         ; обработчик прерывания
 450           PUSH    BC         ; сохранение регистров
 460           PUSH    DE
 470           PUSH    HL
 480  TEST     LD      A,(COUNT)  ; A=счетчик повторений
 490           OR      A          ; есть что играть ?
 500           JR      Z,EXIT
 510           LD      HL,(CURADD); HL=текущий адрес
 520  NEXT     LD      A,(HL)
 530           INC     HL
 540           CP      254        ; A=254 ? (начало цикла)
 550           JR      NZ,CONT1
 560           LD      (ADDR),HL  ; изменение начального адреса
 570           JR      NEXT
 580  CONT1    CP      255        ; A=255 ? (конец)
 590           JR      NZ,CONT2
 600           LD      HL,(ADDR)  ; восстановление начального
 610           LD      (CURADD),HL; адреса блока данных
 620           LD      HL,COUNT
 630           DEC     (HL)       ; уменьшение счетчика
                                    повторений
 640           JR      TEST
 650  CONT2    OR      A          ; A=0 ? (переключатель)
 660           JR      NZ,CONT3
 670           LD      A,(FLAG)
 680           CPL                ; инвертирование A
 690           LD      (FLAG),A
 700           JR      NEXT
 710  CONT3    LD      B,A        ; B=частота
 720           LD      C,(HL)     ; C=длительность
 730           INC     HL
 740           LD      (CURADD),HL; сохранение текущего адреса
 750           LD      A,(FLAG)   ; A=флаг
 760           OR      A          ; A=0 ?
 770           LD      A,7        ; A=цвет бордюра
 780           JR      NZ,NOISE
 790  TONE     XOR     16         ; воспроизведение тона
 800           OUT     (254),A
 810           PUSH    BC
 820  PAUSE    DJNZ    PAUSE
 830           POP     BC
 840           DEC     C
 850           JR      NZ,TONE
 860           JR      EXIT
 870  NOISE    LD      HL,1000    ; воспроизведение шума
 880           LD      D,A
 890  NOIS2    LD      A,(HL)
 900           AND     248
 910           OR      D
 920           OUT     (254),A
 930           PUSH    BC
 940  PAUS2    DJNZ    PAUS2
 950           POP     BC
 960           INC     HL
 970           DEC     C
 980           JR      NZ,NOIS2
 990  EXIT     POP     HL         ; восстановление регистров
1000           POP     DE
1010           POP     BC
1020           POP     AF
1030           RST     56         ; вызов стандартного
                                    обработчика
1040           RET                ; возврат
2
   Порядок использования этого пакета дол-
жен быть следующим. В начале работы  нужно
вызвать подпрограмму SINIT, которая  вклю-
чит 2-ой режим прерываний. В  тот  момент,
когда Вам нужно получить звук, надо занес-
ти в регистр HL адрес блока данных, в  ре-
гистр A - число повторений и вызвать  под-
программу NEWFX. Затем, если  Вам  по  ка-
кой-либо причине надо выключить  звук  или
продлить его звучание, занесите в  регистр
A новое число повторений и  вызовите  под-
программу MUTE.  Кроме того, эту  подпрог-
рамму  можно  использовать  для  включения
последнего звучавшего эффекта. По  оконча-
нии работы (или если в  программе  предус-
мотрены  обращения  к  дисководу)  следует
вызвать подпрограмму  SSTOP, которая  вос-
становит стандартный режим прерываний.
   Серия команд JP в начале пакета  сдела-
на для удобства. Благодаря ей все подпрог-
раммы этого пакета могут вызываться по со-
седним адресам:

       SINIT - 60000 (#EA60)
       SSTOP - 60003 (#EA63)
       NEWFX - 60006 (#EA66)
       MUTE  - 60009 (#EA69)

   К сожалению, с помощью  прерываний  не-
возможно получить достаточно  чистый  тон.
Поэтому, а также из-за совсем не музыкаль-
ного формата данных, эта программа вряд ли
может использоваться для создания  музыки.
Но для звуковых эффектов она в самый раз.
   Вот  пример  использования  приведенной
программы:
1415.
 10            ORG     50000
 20            CALL    60000
 30            LD      HL,SNDFX
 40            LD      A,3
 50            CALL    60006
 60            RET
 70  SNDFX     DEFB    200,5,250,4,200,5,100,10,75,13,50,20,255
2
   Строку 70 можно заменить на следующую:
1415.
 70  SNDFX     DEFB    50,20,75,13,100,10,200,5,250,4,50,20,255
2
   И последнее. Если в Вашей программе  не
очень много движущихся объектов на  экране
и длительность звукового эффекта достаточ-
но мала  (около полсекунды или меньше), то
его можно использовать без всяких прерыва-
ний - задержка заметна не будет.




Другие статьи номера:

Help - Описание оболочки электронного издания "ZX-FORUM 4".

Секреты успешного дизайна - глава для книги "Дизайн Ваших программ"

Экранные эффекты - Бегущая строка из R-Type.

Экранные эффекты - гашения экрана из Zynaps.

Экранные эффекты - "сворачивание" экрана из Comando Tracer.

Экранные эффекты - плавное "затухание" экрана из Сommando Tracer.

Экранные эффекты - модификация символьного набора для получения оригинального стилизованного шрифта из игры Rockstar.

Экранные эффекты - "выбегающая строка" из игры Rockstar.

Экранные эффекты - "наливающийся" экран из игры Rockstar.

Экранные эффекты - сложный многоступенчатый эффект из игры Bubbler.

Новые 40 лучших процедур - скроллинг экрана, слияние двух картинок, инвертирование экрана, поворот символов, замена атрибутов, заливка замкнутого контура, вычисление адресов в экране, копирование части экрана и т.д.

Технология спрайтов - часть 1: введение.

Технология спрайтов - часть 2: охота на спрайты (поиск и выдирание).

Технология спрайтов - часть 3: форматы спрайтов.

Технология спрайтов - часть 4: форматы спрайтов с маской.

Технология спрайтов - часть 5: структура спрайтовых блоков (как уживаются в памяти спрайт и маска, какие данные помогают нам оперативно находить адрес спрайта в памяти и многое другое.)

Технология спрайтов - часть 6: подготовка данных к печати.

Технология спрайтов - часть 8: печать спрайтов (координаты заданы в знакоместах).

Технология спрайтов - часть 9: печать спрайтов (координаты заданы в пикселях).

Технология спрайтов - часть 10: обзор программ для работы со спрайтами и графикой.

Мир звуков Спектрума - глава 1: Физика звука.

Мир звуков Спектрума - глава 2: Оператор BEEP, Создание эффектов на BEEPе, Создание музыки на BEEPе.

Мир звуков Спектрума - глава 3: Как получается звук (устройство BEEP'ра и способы звукоизвлечения).

Мир звуков Спектрума - глава 4: Программирование звука на ассемблере.

Мир звуков Спектрума - глава 4.1: Программирование звуковых эффектов - Тон, Шум, Комплексы эффектов.

Мир звуков Спектрума - глава 4.2: Программирование звуковых эффектов - Управление громкостью.

Мир звуков Спектрума - глава 4.3: Программирование звуковых эффектов - Управление тембром.

Мир звуков Спектрума - глава 4.4: Программирование звуковых эффектов - Программирование музыки.

Мир звуков Спектрума - глава 4.5: Программирование звуковых эффектов - Многоголосые мелодии (полифония).

Мир звуков Спектрума - глава 4.6: Обработка внешних сигналов - оцифровка.

Мир звуков Спектрума - глава 4.7: Обработка внешних сигналов - Реверберация.

Мир звуков Спектрума - глава 4.8: Синтезирование речи.

Мир звуков Спектрума - глава 4.9: воспроизведение звука на прерываниях.

Мир звуков Спектрума - глава 5: Оператор PLAY для музыкального сопроцессора AY- 3-8910 (AY-3-8912).

Мир звуков Спектрума - глава 5.1: Создание эффектов оператором PLAY.

Мир звуков Спектрума - глава 5.2: Создание музыки на PLAYе.

Мир звуков Спектрума - глава 6.1: описание регистров музыкального сопроцессора AY- 3-8910 (AY-3-8912).

Мир звуков Спектрума - глава 6.2: Программирование эффектов и музыки под музыкальный сопроцессор AY- 3-8910 (AY-3-8912).

Мир звуков Спектрума - глава 7: Обзор программного обеспечения ZX-Spectrum для создания звуков и музыки.

Мир звуков Спектрума - глава 7.1: Редактор звуковых эффектов SUPER SOUND.

Мир звуков Спектрума - глава 7.2: Музыкальный редактор Wham the Music Box.

Мир звуков Спектрума - приложения 1, 2: листинги звуковых эффектов SUPER SOUND'а, советы по использованию ассемблера.


Темы: Игры, Программное обеспечение, Пресса, Аппаратное обеспечение, Сеть, Демосцена, Люди, Программирование

Похожие статьи:
От автора - Завтра 1 сентября...
PROFI CLUB - Конверторы для PROFI: PCX VIEW & CONVERTOR v2.10, PCX 256 , GIF-VIEWER.
ZX-Review - пособие "как сделать журнал на Спектруме".
Enlight'96 - небольшое интевью с редактором журнала ZX-Format, Андpеем Рачкиным.
Интервью - Большое интервью с группой ANTARES.

В этот день...   21 ноября