AY-3-8910/12 ZX Spectrum Sound Chip Emulator

AY

Формат является родным для ZX Spectrum и Amstrad CPC, поэтому может проигрываться как в эмуляторах, так и на реальных компьютерах ZX Spectrum и Amstrad CPC без использования специальных плееров.

Формат этого файла был предложен автором plug-in’а DeliAY к DeliTracker’у (компьютер Amiga). Имя этого человека Patrik Rak. На IBM PC эти файлы стало возможно послушать благодаря программке AYPlay James McKay’я. К этой программе прилагается также утилита AYMake, но она имеет ряд ограничений, не позволяющая использовать возможности формата AY полностью. Нижеследующее описание составлено в результате моей годовой работы с AY-файлами, но во все тонкости этого формата удалось проникнуть лишь после продолжительной переписки с Patrik Rak’ом.

Итак, как уже было сказано, формат разрабатывался под Amiga с ее процессором MC68000. В связи с этим все данные размером в слово представлены в порядке “первый байт – старший”. Кроме того, этот процессор накладывает ещё одно ограничение на AY-формат – необходимо, чтобы все двухбайтовые слова были выровнены на двухбайтовые смещения относительно начала AY-файла. Второе важное замечание – все указатели в этом формате являются числами со знаком и фактически являются смещением относительно текущей позиции в файле до нужных данных. Диапазон такого смещения от –32768 до +32767. Это накладывает достаточно жесткие ограничения на размер AY-файла, вполне можно столкнуться с ситуацией, что при конкретных условиях создать AY-файл не возможно.

AY-файл является последовательностью записей. Порядок следования записей не имеет никакого значения, за исключением заголовка, который находится в самом начале файла. Структура заголовка следующая.

Смещение        Длина в байтах  Обозначение     Описание
+0              4               FileID          Идентификатор файла ‘ZXAY’
+4              4               TypeID          Тип файла. Эмулятор пока поддерживает два типа ‘EMUL’, то есть тот, для которого необходима эмуляция процессора Z80, и ‘AMAD’, который является аналогом FXM
+8              1               FileVersion     Версия файла, можете использовать это поле по своему усмотрению, однако автор формата рекомендует нумеровать версии по порядку. Первую версию можно обозвать 0, если в последствии что-нибудь понадобится изменить и переделать, новый файл можно обозвать 1, и так далее.
+9              1               PlayerVersion   Версия проигрывателя, который необходим для проигрывания данного AY-файла. Пока существует 3 версии проигрывателей по мере их развития.
                                                0       Используйте ноль, если не знаете, какой версии проигрыватель Вам нужен.
                                                1       Самая первая версия.
                                                2       Первые 256 байт адресного пространства заполняются кодом 0xC9 (RET).
                                                3       Последняя на сегодняшний день версия, полная эмуляция Z80, плюс поддержка порта динамика Спектрума, подробно описано ниже.
+10             2               PSpecialPlayer  Это для AY-файлов, которые содержат проигрыватель в кодах MC68000. Патрик Рак говорит, что он сделал только один такой файл ещё на Амиже, поэтому на это поле можно не обращать внимания.
+12             2               PAuthor         Смещение до строки с завершающим нулем, в которой хранится имя автора всех песен в данном AY-файле.
+14             2               PMisc           Аналогично, но до строки с прочей информацией.
+16             1               NumOfSongs      Количество мелодий в файле, уменьшенное на 1.
+17             1               FirstSong       Номер песни, которая должна исполняться первой (тоже уменьшено на 1).
+18             2               PSongsStructure Относительное смещение до первой записи “Структура песни”.

Таким образом, размер заголовка равен 20 байтам. Последнее смещение указывает на записи “Структура песни” (по одной записи на каждую песню, эти записи идут друг за другом). Структура любой из записей “Структура песни” следующая.

+0              2               PSongName       Относительное смещение до строки с завершающим нулем, в которой содержится имя песни.
+2              2               PSongData       Смещение до записи “Данные песни”

Всё, что описано выше, справедливо для любого AY-файла. Описанное ниже, справедливо только для типа ’EMUL’.

Запись “Данные песни” для типа ‘EMUL’ имеет следующую структуру.

+0              1               AChan           Номер канала компьютера Amiga, который будет использован для эмуляции канала A AY.
+1              1               BChan           Номер канала компьютера Amiga, который будет использован для эмуляции канала B AY.
+2              1               CChan           Номер канала компьютера Amiga, который будет использован для эмуляции канала C AY.
+3              1               Noise           Номер канала компьютера Amiga, который будет использован для эмуляции канала шума AY.
                                                Наиболее типично для этих четырех байт сочетание 0, 1, 2, 3. Допускается использование указанных номеров в любом порядке. Однако все это актуально только при проигрывании AY-файла на Amiga.
+4              2               SongLength      Продолжительность музыки в 1/50 секунды. Нуль означает то, что длина неизвестна (бесконечна).
+6              2               FadeLength      Продолжительность затухания звука в конце мелодии в 1/50 секунды.
+8              1               HiReg           Содержимое верхних половинок всех общих регистров Z80 перед началом эмуляции (AF, AF', HL, HL', DE, DE', BC, BC', IX и IY).
+9              1               LoReg           Содержимое нижних половинок тех же регистров, даже регистров флагов.
+10             2               PPoints         Относительное смещение до записи “Указатели”.
+12             2               PAddresses      Относительное смещение до записи “Блоки данных”.

Запись “Указатели” проста. Она содержит адреса стека и процедур инициализации и проигрывания данной мелодии.

+0              2               Stack           Значение регистра SP перед началом эмуляции.
+2              2               INIT            Адрес подпрограммы инициализации песни в адресном пространстве Z80.
+4              2               INTERRUPT       Адрес подпрограммы проигрывания (вызывается 50 раз в секунду).

Запись “Блоки данных” тоже проста. Она состоит последовательностей по три слова. Конец такой последовательности определяется первым нулевым словом (то есть Address = 0).

+0              2               Address1        Адрес первого блока в памяти Z80
+2              2               Length1         Длина первого блока в байтах.
+6              2               Offset1         Относительное смещение до этого блока в данном AY-файле.
+8              2               Address2        Адрес второго блока в памяти Z80
+10             2               Length2         Длина второго блока в байтах.
+12             2               Offset2         Относительное смещение до этого блока в данном AY-файле.
и так далее, пока не будет встречено Address = 0, что означает конец записи “Блоки данных”.

Если вы хотите, чтобы Ваш собственный проигрыватель AY-файлов проигрывал большинство ныне существующих файлов, стоит придерживаться следующих правил (они позволят проиграть даже некорректно созданные AY-файлы) при загрузке блоков:

1. Если Address + Length > 65536, необходимо уменьшить длину блока Length так, чтобы эта сумма не превышала 65536.
2. Если ТекущаяПозицияВФайле + Offset + Length > РазмерФайла, опять таки нужно подкорректировать Length.

А теперь подробно о том, как проигрыватель версии 3 должен проигрывать AY-файлы типа EMUL.

1.  Заполнить диапазон #0000–#00FF байтом #C9.
2.  Заполнить диапазон #0100–#3FFF байтом #FF.
3.  Заполнить диапазон #4000–#FFFF байтом #00.
4.  Поместить по адресу #0038 байт #FB.
5.  Если INIT для данной песни равен нулю, необходимо поместить адрес первого загруженного блока в первой инструкции CALL (смотри следующие пункты 6 и 7).
6.  Если INTERRUPT для данной песни равен нулю, необходимо поместить по нулевому адресу следующий плеер:

        DI
        CALL INIT
LOOP:   IM 2
        EI
        HALT
        JR LOOP

7. Если INTERRUPT не равен нулю, то нужно использовать другой плеер:

        DI
        CALL INIT
LOOP:   IM 1
        EI
        HALT
        CALL INTERRUPT
        JR LOOP

8.  Загрузить все блоки для данной песни.
9.  Загрузить в нижние половинки общих регистров Z80, включая флаговые, значение LoReg.
10. Загрузить в верхние половинки регистров Z80 значение HiReg.
11. Загрузить в регистр I значение 3 (номер версии плеера).
12. Загрузить в регистр SP значение Stack.
13. Загрузить в PC значение 0.
14. Запретить прерывания и установить режим IM0.
15. Произвести сброс AY.
16. Запустить эмуляцию Z80.

Обратите внимание, что блоки можно загружать прямо поверх стандартного плеера. Вы можете использовать это, когда возникает необходимость использовать свои коды проигрывателя вместо стандартного. В этом случае, можно помещать плеер по адресу INIT или даже #0001. Вообще, блоки данных можно загружать по любому адресу, кроме 0.

Теперь несколько слов о типе ‘AMAD’.

Запись “Данные песни” для типа ‘AMAD’ имеет следующую структуру.

+0              2               AllocAddress    Адрес расположения блока данных в памяти Спектрума.
+2              1               Andsix          Данный параметр равен либо 31, либо 15 и отражает особенность некоторых плееров Amadeus, в которых по команде AND после сложения текущего значения шума с параметром команды 8D (добавка к шуму) происходит обрезание результата до 5 или 4 бит соответственно.
+3              1               Loops           Количество повторов (loops).
+4              2               LoopLen         Длина мелодии (одного loop) в прерываниях.
+6              2               FadeOffset      Precise fade specification (не используется в Ay_Emul)
+8              2               FadeLen         How long to fade (не используется в Ay_Emul)
+10             1               AChan           Номер канала компьютера Amiga, который будет использован для эмуляции канала A AY.
+11             1               BChan           Номер канала компьютера Amiga, который будет использован для эмуляции канала B AY.
+12             1               CChan           Номер канала компьютера Amiga, который будет использован для эмуляции канала C AY.
+13             1               Noise           Номер канала компьютера Amiga, который будет использован для эмуляции канала шума AY.
                                                Наиболее типично для этих четырех байт сочетание 0, 1, 2, 3. Допускается использование указанных номеров в любом порядке. Однако все это актуально только при проигрывании AY-файла на Amiga.
+14             ???             ZXData          Оригинальный блок данных со Спектрума. Полное описание этого блока приведено в описании FXM файлов в данной справочной системе.

Обратите внимание на то, что и EMUL, и AMAD файлы могут содержать более одной мелодии в одном AY-файле.

Теперь немного о недостатках формата и о том, как именно описанные правила применены в данной версии AY эмулятора.

Первый недостаток заключен в том, что спецификация допускает понятие “бесконечное проигрывание”, то есть когда значение поля SongLength равно нулю. В AY эмуляторе такого понятия нет, и поэтому такие файлы вместо “бесконечности” будут проигрываться 15000 прерываний.

Второй недостаток заключается в неясности термина “1/50 секунды”. Если это период прерываний Спектрума, то понятно, что он зависит, по крайней мере, от двух параметров – частоты Z80 и количества тактов Z80 между прерываниями (по крайней мере, так реализованы отечественные аналоги Спектрума). Однако ни в спецификации по AY-файлам, ни по проигрывателям, ничего не сказано о значениях для этих параметров. В данной версии эмулятора по умолчанию используются частота Z80 3494400 Гц и период прерываний 69888 тактов, (то есть получается та самая 1/50 секунды).

Третий недостаток заключается в том, что нет возможности загрузить блок по адресу #0000, поскольку нулевое слово означает конец последовательности блоков данных. Эта проблема может быть решена за счет того, что самый первый блок может иметь нулевой адрес, однако для совместимости с другими версиями AY-проигрывателей на Amiga и на PC в данном эмуляторе это не сделано.

Ещё можно добавить, что формат AY подразумевает только модель памяти 48К. Однако, музыку, которую было бы нельзя впихнуть в рамки 48К памяти не так уж и много.

Развитие формата на PC произошло благодаря James McKay, который реализовал поддержку динамика Спектрума, а также в целом более качественную эмуляцию Z80. Стоит отметить, что благодаря утилите AYMake McKay’я, было загублено много AY-файлов, сделанных ещё на Amiga, поскольку AYMake не поддерживает поля, связанные с продолжительностью звучания модулей. В данный момент bcass (хозяин сайта Project AY) переделал многие AY файлы своего проекта, добавив в них эту информацию. Patrik Rak занимается plug-in'ом для DeliPlayer, и теперь мы можем увидеть авторский вариант поддержки AY-файлов на PC. Надо сказать, что эмуляция Z80 там плохая, например, последний плеер Alone Coder’а от Pro Tracker v3.66 в DeliPlayer’е не работает.

Ну а с остальными достоинствами и недостатками AY-файлов вы можете разобраться сами, если решите вплотную заняться их выдиранием из программ Speccy. Мои утилиты с исходными текстами для создания и работы с AY-файлами вы можете найти на официальном сайте эмулятора.