gamedev Tutorials Программирование игр

               Программирование Adlib/SoundBlaster
   			ЧМ Синтезатор
                      Версия 2.0 ( 24 февраля 1992 )

             Авторское Право 1991 (c), 1992 Jeffrey S. Lee

                          jlee@smylex.uucp


Все числа в шестнадцетеричной системе, если специально не оговоренно.



                    Часть 1 - Порты звуковой карты

Звуковая плата программируется посылкой данных во внутренние регистры
через два порта ввода/вывода:

        0x0388  - порт Адреса / Состояния (R/W)
        0x0389  - порт Данных             (W/O)

Sound Blaster Pro воспроизводит стерео музыку, обращение к каналам
происходит также, но базовый адрес для левого канала 0x220, правого
0x222. Sound Blaster совместим с Adlib. Через 0x388 и 0x389 порты
происходит вывод музыки через оба динамика.

В звуковой плате 244 внутренних регистра (01-F5). Для того чтобы
записать значение в регистр:
   - запишите номер регистра в порт адреса;
   - запишите значение в регистр данных.

После записи порт адреса надо 6 раз считать из него, перед посылкой
данных в регистр данных. После записи данных 30 раз, прежде, чем
можно будет снова продолжить программирование карты. В руководстве
по Adlib сказано, что ожидать надо 3.3 микросекунды для адреса,
и 23 мкс для данных.

Регистры звуковой карты только на запись.

Для того того чтобы прочитать байт состояния звуковой карты, просто
прочитайте порт 0x388. Байт состояния имеет следующую структуру:

         7      6      5      4      3      2      1      0
     +---------+--------+--------+------+------+------+------+------+
     | Оба     | таймер | таймер |                 Неиспользуется   |
     | таймера |      1 |      2 |                                  |
     +---------+--------+--------+------+------+------+------+------+

     Бит 7 - установлен если оба таймера истекли.
         6 - установлен если 1 таймер установлен.
         5 - установлен если 2 таймер установлен.



                       Часть 2 - Регистры

В этой таблице приведены функции каждого регистра в звуковой карты.
Регистры объясняются после таблицы. Не приведенные регистры неиспользуются.

   Адрес        Функци
   -------      ----------------------------------------------------
     01         Тест LSI / Выбор формы волны
     02         Таймер 1
     03         Таймер 2
     04         Флаги управления Таймера
     08         Речевой режим синтеза / Способ кодирования нот
   20. .35      Тремоло / Вибрато / Постоянный уровень /
		Изменение длительности / Умножение частоты
   40. .55      Изменение уровня / Уровень сигнала ( громкость )
   60. .75      Атака / Спад после атаки
   80. .95      Постояный уровень / Затухание
   A0.. A8      Частота ( 8 младших битов )
   B0.. B8      Включить ноту / Октава / Частота ( 2 старших бита )
     BD         Глубина тремоло / вибрато / контроль ритма
   C0.. C8      Величина обратной связи / режим обьединения цепей
   E0.. F5      Форма волны

Группы из двадцати двух регистров ( 20-35, 40-55, и т.д.. ) содержат
информацию о 9 инструментах. Информация о каждом инструменте состоит
из байта описания цепи 1, и байта описания цепи 2. Следующая таблица
показывает смещения в пределах каждой группы регистров для каждой цепи.

   Канал          1  2  3  4  5  6  7  8  9
   Цепь 1        00 01 02 08 09 0A 10 11 12
   Цепь 2        03 04 05 0B 0C 0D 13 14 15

Таким образом, адрес байта атака/спад для канала 3 - 62 для цепи 1,
и 65 для цепи 2. ( Адрес второй цепи - всегда равняется адрес первой
цепи плюс три ).

Чтобы иллюстрировать эту связь, приведены адреса необходимые чтобы
управлять каналом 5:

    29 - Цепь 1 Тремоло
    2C - Цепь 2 Тремоло
    49 - Цепь 1 Уровень
    4C - Цепь 2 Уровень
    69 - Цепь 1 Атака
    6C - Цепь 2 Атака
    89 - Цепь 1 Затухание
    8C - Цепь 2 Затухание
    A4 - Частота ( 8 младших битов )
    B4 - Включить ноту / Октава / Частота ( 2 старших бита )
    C4 - Величина обратной связи / режим обьединения цепей
    E9 - Цепь 1 Форма Волны
    EC - Цепь 2 Форма Волны



                       Пояснения работы регистров карты

Байт 01 - Этот байт обычно используется чтобы проверять LSI устройство. Все
          биты обычно установлены в ноль. Бит 5 разрешает выбор формы волны
	  0 - синусоидальная, 1 - определяется E0-F5


Байт 02 - Таймер 1. Если таймер 1 доступен, значение в этом
          регистре будет увеличиваться пока не переполняется. После
          переполнения, звуковая плата будет вызывать прерывание таймера
	  ( int 08 ) и установит биты 7 и 6 в байте состояния. Счетчик
          этого таймера увеличивается каждые 80 микросекунд.


Байт 03 - Таймер 2. Если таймер 1 доступен, значение в этом
          регистре будет увеличиваться пока не переполняется. После
          переполнения, звуковая плата будет вызывать прерывание таймера
	  ( int 08 ) и установит биты 7 и 6 в байте состояния. Счетчик
          этого таймера увеличивается каждые 320 микросекунд.


Байт 04 - Служебный байт таймера

        7     6     5     4     3     2     1     0
     +-----+-----+-----+-----+-----+-----+-----+-----+
     | IRQ | T1  | T2  |  Неиспользуется | T2  | T1  |
     | RST | MSK | MSK |                 | CTL | CTL |
     +-----+-----+-----+-----+-----+-----+-----+-----+
      сброс маски                         старт таймеров
    таймера таймеров

          Бит 7 - Сброс флажков таймеров 1 & 2. При этом
                   все другие биты игнорируются.
          Бит 6 - Маска таймера 1. При установлен, то бит 0 игнорируется.
          Бит 5 - Маска таймера 2. При установлен, то бит 1 игнорируется.
          Бит 1 - Когда очищен, то таймер 2 не работает.
                  Когда установлен, значение из байта 03 загружаетс
		  в таймер 2, и начинается увеличиваться.
          Бит 0 - Когда очищен, то таймер 1 не работает.
                  Когда установлен, значение из байта 02 загружаетс
		  в таймер 1, и начинается увеличиваться.


Байт 08 - Речевой режим синтеза / Способ кодирования нот.

        7     6     5     4     3     2     1     0
     +-----+-----+-----+-----+-----+-----+-----+-----+
     | CSM | Key |   Неиспользуется                  |
     | Sel | Spl |                                   |
     +-----+-----+-----+-----+-----+-----+-----+-----+

          Бит 7 - Когда установлен, выбирает композитный режим синтеза речи
                  ( все KEY-ON биты должен быть очищены ). Когда сброшен,
                   то выбор FM режима.

          Бит 6 - Выбор режима кодирования нот.


Байты 20-35 - Тремоло / Вибрато / Постоянный уровень /
	      Изменение длительности / Умножение частоты

        7     6     5     4     3     2     1     0
     +-----+-----+-----+-----+-----+-----+-----+-----+
     | Amp | Vib | EG  | KSR | Умножение частоты     |
     | Mod |     | Typ |     |                       |
     +-----+-----+-----+-----+-----+-----+-----+-----+
      "Тремоло"   Постоянный
		  уровень
	   "Вибрато"    Изменение
			длительности

          Бит 7 - Применяется "тремоло" когда установлено; глубина
                  управляется флажком AM-Depth по адресу BD.
          Бит 6 - Применяется "вибрато" когда установлено; глубина
                  управляется флажком VIB-depth по адресу BD.
          Бит 5 - Если установлен, постоянный уровень сигнала поддерживаетс
		  пока не отпущено; когда сброшен, звук начинается без задержки
                  после постоянной фазы.
          Бит 4 - Когда установлен, то включает режим изменения длительности
		  сигнала с ростом частоты
          Бит 3-0 - Эти биты указывают какая гармоника будет
                  воспроизводить звук ( или модуляцию ) в отношении частоты
		  воспроизводимого звука
		  ( коэффициент умножения частоты )

                      0 - на одну октаву ниже
                      1 - в определеной частоте звука
                      2 - на одна октаву выше
                      3 - на октаву и пятый выше
                      4 - Две октавы выше
                      5 - Две октавы и мажор треть выше
                      6 - Две октавы и пятый выше
                      7 - Две октавы и минор седьмой выше
                      8 - Три октавы выше
                      9 - Три октавы и мажор секунда выше
		      A - три октавы и мажор треть выше
                      B - "        """ """
		      C - три октавы и пятый выше
                      D - "        """ " "
		      E - три октавы и мажор седьмой выше
                      F - "        """ """


Байты 40-55 - Изменение уровня / Уровень сигнала ( громкость )


        7     6     5     4     3     2     1     0
     +-----+-----+-----+-----+-----+-----+-----+-----+
     | Изменение |       Общий Уровень               |
     | Уровня    | 24      12     6     3   1.5  .75 | < - dB
     +-----+-----+-----+-----+-----+-----+-----+-----+

          Биты 7-6 - устанавливают как будет уменьшатся выходной уровень
		     с ростом частоты:

                          00 -    нет изменени
                          10 -    1.5 DB/8ve
                          01 -    3 DB/8ve
                          11 -    6 DB/8ve

          Биты 5-0 - контролирует общий выходной уровень цепи.
                     Когда все биты очищены то самый громкий;
		     Когда все установлены то самый тихий.
		     Определяют уровень сигнала. Когда цепь включена
		     аддитивно или является генератором несущей,
		     они устанавливают громкость звучания.
		     Если цепь используется для генерации
		     модулирующего сигнала, эти разряды задают
		     глубину модуляции. Учтите, что громкость
		     от их содержимого зависит не линейно. При
		     увеличении на 1 уменьшается на 0.75 DB



Байты 60-75 - Атака / Спад после атаки

        7     6     5     4     3     2     1     0
     +-----+-----+-----+-----+-----+-----+-----+-----+
     |   Скорость            | Скорость              |
     |   Атаки               | Спада                 |
     +-----+-----+-----+-----+-----+-----+-----+-----+

          Биты 7-4 - скорость атаки. 0 - низкая, F - быстрая.
          Биты 3-0 - скорость спада. 0 - низкая, F - быстрая.


Байты 80-95 - Постоянный уровень / Затухание

        7     6     5     4     3     2     1     0
     +-----+-----+-----+-----+-----+-----+-----+-----+
     |    Постоянный Уровень | Скорость              |
     | 24    12    6     3   | затухания             |
     +-----+-----+-----+-----+-----+-----+-----+-----+

          Биты 7-4 - постоянный Уровень. 0 самый громокий, F самый тихий.
          Биты 3-0 - Скорость затухания. 0 - медленно, F самый быстрый.


Байты A0-B8 - Частота ( 8 младших битов ) /
	      Включить ноту / Октава / Частота ( 2 старших бита )

        7     6     5     4     3     2     1     0
     +-----+-----+-----+-----+-----+-----+-----+-----+
     |        Восемь младщих битов частоты           | (A0-A8)
     |                                               |
     +-----+-----+-----+-----+-----+-----+-----+-----+

        7     6     5     4     3     2     1     0
     +-----+-----+-----+-----+-----+-----+-----+------+
     | Неисполь- | Вкл |          Октава |Два старших | (B0-B8)
     | зуется    | Ноту|                 |бита частоты|
     +-----+-----+-----+-----+-----+-----+-----+------+

	  Эти регистры задают ноту и октаву для каждого из девяти
	  голосовых каналов. Отметим, что для работы с синтезатором
	  достаточно знать частоты нот в пределах одной октавы.

	  Бита 5 -   Канал звучит когда установлен.
          Биты 4-2 - Октава (0-7). 0 низкая, 7 высокая.
          Биты 1-0 - Старшие биты частоты.

     Кодирование нот в октаве 4:

           Код          Частота   Нота
           16B          277.2     C(#)(до#)
           181          293.7     D (ре)
           198          311.1     D(#)(ре#)
           1B0          329.6     E (ми)
           1CA          349.2     F (фа)
           1E5          370.0     F(#)(фа#)
           202          392.0     G(соль)
           220          415.3     G(#)(соль#)
           241          440.0     A(ля)
           263          466.2     A(#)(ля#)
           287          493.9     B(си)
           2AE          523.3     C(до)

Байты C0-C8 - Величина обратной связи / режим обьединения цепей

        7     6     5     4     3     2     1     0
     +-----+-----+-----+-----+-----+-----+-----+-----+
     |       Неиспользуется  |  Глубина        | Alg |
     |                       | Обратной Связи  |     |
     +-----+-----+-----+-----+-----+-----+-----+-----+
						Режим обьединения сигналов
						колебательных цепей.
          Биты 3-1 - Величина обратной связи. Если все три бита = 0,
                     то обратной связи нет. При значениях 1-7, цепь 1
		     будет посылать часть вывода обратно самостоятельно.
		     1 меньше 7 - максимум.
          Бита 0 -   Если = 0, то цепь 1 модулирует цепь 2. В этом случае,
	  	     только цепь 2 воспроизводит звук. Если = 1, обе
		     цепи воспроизводят звук. Комплексные звуки легко
		     создаются, если = 0.


Байт BD - Глубина тремоло / вибрато / контроль ритма

        7     6     5     4     3     2     1     0
     +-----+-----+-----+-----+-----+-----+-----+-----+
     | AM  | Vib | Rhy | BD  | SD  | TOM | Top | HH  |
     | Dep | Dep | Ena |     |     |     | Cym |     |
     +-----+-----+-----+-----+-----+-----+-----+-----+
     Глубина      режим       Малый барабан     Тарелки
     тремоло      ударных     включить          включить
	   Глубина     Большой      Там-там
	   вибрато     барабан      включить
		       включить           Цимбалы
					  включить

	  Бит 7 - задает глубину "тремоло" =1 - 4.8db, =0 - 1db.
	  Бит 6 - определяет глубину "вибрато" =1 - 14%, =0 - 7%.
	  Бит 5 - включает режим мелодии (0) ( 9 голосов )
	   	  или ударных (1) ( 6 голосов ).
	          Если установлен режим ударных используютс
	          биты с 4 по 0. Смещение регистров колебательных
		  цепей в этом  режиме такое:

   Канал          1  2  3  4  5  Большой Малай  Там-там Цимбалы Тарелки
   				 барабан барабан
   Цепь 1        00 01 02 08 09       0A    14     12      15     11
   Цепь 2        03 04 05 0B 0C       0D



Байты E0-F5 - Выбор Формы Волны

        7     6     5     4     3     2     1     0
     +-----+-----+-----+-----+-----+-----+-----+------+
     |               Неиспользуется      | Выбор формы|
     |                                   | волны      |
     +-----+-----+-----+-----+-----+-----+-----+------+

          Биты 1-0 - Когда бит 5 регистра 01 установлен, выходна
                     форма волны будут искажаться согласно форме волны
                     обозначенной этими двумя битами. Мы будем пробовать
                     изображать схематически их здесь, но это трудно

         ___              ___            ___    ___       _      _
        /   \            /   \          /   \  /   \     / |    / |
       /_____\_______   /_____\_____   /_____\/_____\   /__|___/__|___
              \     /
               \___/

            00              01               10               11



                           Обнаружение Звуковой Платы

  Согласно руководству AdLib, "официальный" метод обнаружения Adlib

       1) Сбросьте оба таймера записав 60h в регистр 4.
       2) Разрешите прерывания записав 80h в регистр 4.
       3) Прочитайте регистр состояния ( порт 388-ой ). Сохраните результат.
       4) Запишите FFh в регистр 2 ( Таймер 1 ).
       5) Запустите таймер 1 записав 21h в регистр 4.
       6) Сделайте задержку на 80 микросекунд.
       7) Читайте регистр состояния ( порт 388-ой ). Сохраните результат.
       8) Сбросьте и таймеры и прерывания ( см. шаги 1 и 2 ).
       9) Проверите сохраненные результаты шагов 3 и 7 и AND их с E0h.
          Результат шага 3 должен быть 00h, и результат шага 7 должен
	  быть C0h. Если это правильно, то AdLib-совместимая плата
	  устанавлена в ПЭВМ.

  Другой метод:

PROC Detectadlib                              ;proc to detect adlib
                stc                           ;set the carry flag (default)
                pusha                         ;preserve regs
                mov     dx,0388h              ;use the code posted by lee
                in      al,dx                 ;someone else suggested it...
                cmp     al,0                  ;seems to work
                je      @@there               ;adlib present, clear carry flag
                cmp     al,6                  ;adlib not present if al<>0 OR 6
                jne     @@carryon             ;and again...
                                              ;
@@there:        clc                           ;clear cf, adlib is there
@@carryon:
                popa                          ;restore our regs
                ret                           ;return
ENDP                                          ;end of detect adlib proc


   Официальный метод

AdlibAddr	dw	0388h

WriteFM PROC NEAR
        push    ax
        push    cx
        push    dx
        xchg    al,ah
        mov	dx, cs:AdlibAddr
        out     dx, al
        mov     cx,7
        call    FMwait
        inc	dx
        mov     al,ah
        out     dx,al
        dec     dx
        mov     cx,30
        call    FMwait
        pop     dx
        pop     cx
        pop     ax
        ret
FMwait: in      al,dx
        loop    FMwait
        ret
WriteFM ENDP


;-----------------------------------------------------------------------------
;- Check for FM chip, returns CF = 0 if found, or CF = 1 if not --------------
;-----------------------------------------------------------------------------

TestFMchip      proc    far

        mov     ax, 00100h
        Call    WriteFM
        mov     ax, 00480h
        Call    WriteFM

        mov	dx, cs:AdlibAddr
        in      al, dx
        mov     cl, al
        mov     ax, 002FFh
        Call    WriteFM
        mov     ax, 00421h
        Call    WriteFM

        mov	dx, cs:AdlibAddr
        mov     cx, 100
        call    FMwait
        mov     ch, al

        mov     ax, 00460h
        Call    WriteFM
        mov     al, 80h
        Call    WriteFM

        and     cl, 0E0h
        cmp     cl, 0
        jne     No_FMchip
        and     ch, 0E0h
        cmp     ch, 0C0h
        jne     No_FMchip

        popa
        clc
        ret

No_FMchip:

        popa
        stc
        ret

TestFMchip      endp

Примечания переводчика

   Данный документ составлен Анисимовым С.Ю. 09/1995

   Данными для составления этого документа послужила информация
   из различных источников. Поэтому автор не несет ответственность
   за неверную информацию, и за повреждения техники и тел при
   использовании этого документа.
   
С наилучшими пожеланиями, для всех любителей программировать Adlib !
			   Vale !

PMG  25 Февраля 1999 (c)  Сергей Анисимов