Формат является родным для 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 | Тип данных в контейнере. Ay_Emul пока поддерживает следующие типы: 'EMUL' – эмуляция процессора Z80; 'AMAD' – аналог FXM; 'ST11' – контейнер ST1. |
+8 | 1 | FileVersion | Версия файла, можете использовать это поле по своему усмотрению, однако автор формата рекомендует нумеровать версии по порядку. Первую версию можно обозвать 0, если в последствии что-нибудь понадобится изменить и переделать, новый файл можно обозвать 1, и так далее. |
+9 | 1 | PlayerVersion | Версия проигрывателя, который необходим для проигрывания данного AY-файла. Пока существует 3 версии проигрывателей по мере их развития: 0 – используйте ноль, если не знаете, какой версии проигрыватель вам нужен; 1 – самая первая версия; 2 – первые 256 байт адресного пространства заполняются кодом 0xC9 (RET); 3 – последняя на сегодняшний день версия, полная эмуляция Z80, плюс поддержка порта динамика ZX Spectrum (бипера), подробно описано ниже. |
+10 | 2 | PSpecialPlayer | Это для AY-файлов, которые содержат проигрыватель в кодах MC68000. Патрик Рак говорит, что он сделал только один такой файл ещё на Amiga, поэтому на это поле можно не обращать внимания. |
+12 | 2 | PAuthor | Смещение до строки с завершающим нулём, в которой хранится имя автора всех песен в данном AY-файле. |
+14 | 2 | PMisc | Аналогично, но до строки с прочей информацией. |
+16 | 1 | NumOfSongs | Количество мелодий в файле, уменьшенное на 1. |
+17 | 1 | FirstSong | Номер песни, которая должна исполняться первой (тоже уменьшено на 1). |
+18 | 2 | PSongsStructure | Относительное смещение до первой записи "Структура песни". |
Размер заголовка равен 20 байтам.
Последнее смещение указывает на записи "Структура песни" (по одной записи на каждую песню, эти записи идут друг за другом). Таким образом, и EMUL, и AMAD, и ST11, и другие типы могут содержать более одной мелодии в одном AY-файле.
Смещение | Длина в байтах | Обозначение | Описание |
---|---|---|---|
+0 | 2 | PSongName | Относительное смещение до строки с завершающим нулём, в которой содержится имя песни. |
+2 | 2 | PSongData | Смещение до записи "Данные песни". |
Всё, что описано выше, справедливо для любого AY-файла. Далее описаны типы данных в контейнере.
Смещение | Длина в байтах | Обозначение | Описание |
---|---|---|---|
+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 раз в секунду). Может быть равен нулю (описано далее). |
Смещение | Длина в байтах | Обозначение | Описание |
---|---|---|---|
+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-файлы) при загрузке блоков:
А теперь подробно о том, как проигрыватель версии 3 должен проигрывать AY-файлы типа 'EMUL'.
DI CALL INIT LOOP: IM 2 EI HALT JR LOOP
DI CALL INIT LOOP: IM 1 EI HALT CALL INTERRUPT JR LOOP
Обратите внимание, что блоки можно загружать прямо поверх стандартного плеера. Вы можете использовать это, когда возникает необходимость использовать свои коды проигрывателя вместо стандартного. В этом случае, можно помещать плеер по адресу INIT или даже #0001. Вообще, блоки данных можно загружать по любому адресу, кроме 0.
Ay_Emul работает как проигрыватель версии 3.
Смещение | Длина в байтах | Обозначение | Описание |
---|---|---|---|
+0 | 2 | AllocAddress | Адрес расположения блока данных в памяти ZX Spectrum. |
+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 | Назначение аналогично типу 'EMUL'. |
+11 | 1 | BChan | Назначение аналогично типу 'EMUL'. |
+12 | 1 | CChan | Назначение аналогично типу 'EMUL'. |
+13 | 1 | Noise | Назначение аналогично типу 'EMUL'. |
+14 | ??? | ZXData | Оригинальный блок данных с ZX Spectrum. Полное описание этого блока приведено в описании формата FXM. |
Смещение | Длина в байтах | Обозначение | Описание |
---|---|---|---|
+0 | 1 | AChan | Назначение аналогично типу 'EMUL'. |
+1 | 1 | BChan | Назначение аналогично типу 'EMUL'. |
+2 | 1 | CChan | Назначение аналогично типу 'EMUL'. |
+3 | 1 | Noise | Назначение аналогично типу 'EMUL'. |
+4 | 4 | Unknown | В существующих файлах здесь обычно последовательность (0,0,0,50), но есть один с (0,0,0,255). |
+8 | ??? | ZXData | Оригинальный блок данных с ZX Spectrum. Полное описание этого блока приведено в описании формата ST1. |
Теперь немного о недостатках формата и о том, как именно описанные правила применяются в Ay_Emul.
Первый недостаток заключён в том, что спецификация допускает понятие "бесконечное проигрывание", то есть когда значение поля SongLength равно нулю. В Ay_Emul такого понятия нет, и поэтому такие файлы вместо "бесконечности" будут проигрываться 15000 прерываний.
Второй недостаток заключается в неясности термина "1/50 секунды".
Если это период прерываний ZX Spectrum, то он зависит от двух параметров – частоты Z80 и количества тактов Z80 между прерываниями (по крайней мере, так реализованы отечественные аналоги ZX Spectrum). Однако ни в спецификации по AY-файлам, ни по проигрывателям, ничего не сказано о значениях для этих параметров. В Ay_Emul по умолчанию используются частота Z80 3494400 Гц и период прерываний 69888 тактов (то есть получается та самая 1/50 секунды).
Но если музыка играется без синхронизации с прерываниями, то отсутствие данных о частоте процессора уже критично: если человек, создающий AY-файл, измеряет длительность и переводит её в указанные единицы для одной частоты CPU, а проигрыватель у конечного пользователя играет на другой, то файл либо не доиграется до нужного момента, либо проиграется дальше, чем надо.
Третий недостаток заключается в том, что нет возможности загрузить блок по адресу #0000, поскольку нулевое слово означает конец последовательности блоков данных. Эта проблема может быть решена за счёт того, что самый первый блок может иметь нулевой адрес, однако для совместимости с другими версиями AY-проигрывателей на Amiga и на PC в Ay_Emul это не сделано.
Ещё можно добавить, что формат AY подразумевает только модель памяти 48К. Однако, музыку, которую было бы нельзя впихнуть в рамки 48К памяти не так уж и много.
Развитие формата на PC произошло благодаря James McKay, который реализовал поддержку бипера. Однако его утилита AYMake не поддерживает поля, связанные с продолжительностью звучания модулей и по сети разошлось множество AY-файлов без этой важной информации.
Команда Project AY (энтузиасты формата во главе с bcass) переделала многие существовавшие на тот момент AY-файлы, добавив в них эту информацию, а также существенно пополнила коллекцию.
Patrik Rak выпустил plug-in для DeliPlayer, и теперь мы можем увидеть авторский вариант поддержки AY-файлов на PC.
Tim Fardel сделал плеер SpecAY для реального ZX Spectrum, в результате большую часть коллекции возможно послушать на родном оборудовании.
Ну а с остальными достоинствами и недостатками AY-файлов вы можете разобраться сами, если решите вплотную заняться доработкой существующих или выдиранием новых из программ Speccy. Мои утилиты с исходными текстами для создания и работы с AY-файлами (AYMakeR, aysplitr, ay2sna) вы можете найти на официальном сайте Ay_Emul.
Продолжительность звучания поможет определить утилита YMTOOL.EXE от Arnaud Carre: достаточно конвертировать AY-файл в YM6, задав продолжительность 10–30 минут, и утилита поможет найти тело цикла.