GEMS: Genesis Editor for Music and Sound effects В этой статье пойдет речь об одном очень популярном звуковом движке в играх SMD/Genesis, который носит название GEMS. Он используется в таких достаточно известных и неплохих играх как: Zero Tolerance, Dune: The Battle for Arrakis, Earthworm Jim, Comix Zone и еще куче других. В отличие от своего «коллеги» движка SMPS, GEMS таких ярких разновидностей не имеет. Всю музыку играет здесь z80 с небольшой помощью M68k. Наблюдается комбинированная работа двух этих процессоров. Надо сказать, что некоторое время назад в общий доступ была выложена среда разработки музыки для данного движка и внутри есть неплохая документация о его фичах, но нет таковой о структуре самих данных. Здесь я постараюсь об этом по возможности рассказать.
Составные части мелодии
Вся музыка в формате GEMS лежит в роме в так называемых банках. Используется 4 банка данных GEMS: 1. Patches bank – банк голосов FM и инструментов PSG 2. Sequences bank – банк нотных последовательностей каждой мелодии 3. Modulation bank – банк данных частотной модуляции каждой мелодии (пока неизвестно как работает) 4. Samples bank – банк с PCM сэмплами. Каждый банк имеет заголовок, в котором указываются поинтеры на данные мелодии/модуляции/голоса/сэмпла. Во всех банках, кроме банка с последовательностями, поинтер указывает непосредственно на объект банка.
Исключение: обычно поинтеры всегда размером 2 байта (word), однако в некоторых играх (Vectorman, Comix Zone) поинтеры разделены нулем. То есть по сути размер увеличивается на один байт.
Формат банка с последовательностями рассмотрим ниже. Sequence bank структура Общий вид данных в банке следующий: [поинтер на мелодию 0] [поинтер на мелодию 1] … мелодия 0 [кол-во каналов] [поинтеры на каналы] мелодия 1 [кол-во каналов] [поинтеры на каналы] ... мелодия 0 канал 0 [последовательность нот канала] мелодия 0 канал 1 [последовательность нот канала] ... Формат поинтеров: относительные, остроконечный метод хранения данных, с базой – адрес начала банка.
Dynamic Voice Allocation
Как видите, у каждой мелодии есть свое количество каналов, прямо как в SMPS. Однако GEMS использует свои каналы, которые не связаны с каналами звука Ямахи или PSG. И этих каналов максимум может быть 16! Как же так, скажете вы, ведь на SMD максимум звуковых каналов может быть всего 10 (1 DAC, 6 FM, 3 PSG). Все просто. Используется так называемое динамическое распределение нот по каналам, которым занимается z80. Облегчили, блин, жизнь разработчикам, а хакерам наоборот усложнили! Распределение идет относительно от используемого голоса/инструмента в данный момент времени и от того свободен ли канал или нет. В итоге, неизвестно в каком канале будет играть та или иная нота, до тех пор, пока не придет время воспроизвести ее!
Структура нотной последовательности
Также как и в SMPS, мелодия на движке GEMS состоит из самих нот, байтов, задающих длительность ноты, а также команд (флагов). Но в отличие от того же SMPS, здесь длительность ноты задается до воспроизведения ноты. То есть допустим, в SMPS, чтобы проиграть ноту С0 нужно было записать: $8105, где 5 – длительность ноты. В GEMS это по-другому. В начале, пишется байт, характеризующий текущую величину продолжительности звучания, а потом все последующие ноты играют с данной продолжительностью, пока снова не встретится байт, отвечающий за текущую продолжительность. Еще существуют так называемые «ожидания» - величины простоя после воспроизведения ноты или выполнения команды. Однако работаю они немного по-иному. По сути, величина ожидания – это сумма продолжительности звучания ноты и величины ожидания минус продолжительность звучания. Короче можно считать, что ожидание – это время, выделенное на воспроизведение ноты/выполнение команды.
Величины нот/команд лежат в следующих диапазонах: $0-$5F: Ноты $60-$72: Команды $80-BF: Величины продолжительности звучания нот (сама величина лежит в первых 6 битах) $C0-FF: Величины ожидания (сама величина лежит в первых 6 битах) Числа с $73 до $7F не используются. После всех команд, кроме $60, $64, $65, $6F следует ожидание.
Описание команд
$60 Конец последовательности. $61 Задать номер инструмента для последовательности. Имеет 1 байт параметр. $62 Неизвестно что. $63 Ничего не делает. NOP. $64 Начало цикла. Имеет байт параметр, задающий кол-во повторений цикла. $65 Конец цикла. $66 Вкл/выкл retrigger mode. (?) $67 Вкл/выкл sustain mode. (?) $68 Задать скорость (tempo) для мелодии. Имеет 1 байт параметр – значение скорости. $69 Выключить звук последовательности (Mute). $6A Установить приоритет последовательности. 0 – самый низкий, $7F – самый высокий. Имеет 1 байт параметр – величина приоритета. $6B Начать воспроизведение другой мелодии. Имеет байт параметр – номер мелодии. $6C Модуляция. Меняет pitch. Имеет параметр 2 байта – величина pitch. $6D Неизвестно что. $6E Установить скорость проигрывания сэмплов DAC. Имеет 1 байт параметр – величина скорости. $6F Прыжок на назначенную позицию. Имеет параметр 2 байта – адрес куда прыгать. $70 Записать величину в один из «контейнеров». Имеет 2 параметра – первый: номер контейнера, второй: записываемое значение. $71 Прыжок по условию (оператор ЕСЛИ). Следующие байты имеют вид: [контейнер #][условие][контейнер #][назначение]. Номер условия – Само условие 1 контейнер != контейнер 2 контейнер > контейнер 3 контейнер >= контейнер 4 контейнер < контейнер 5 контейнер <= контейнер остальные числа контейнер == контейнер Если условие истинно, происходит прыжок к заданному адресу, если нет, то не происходит ничего. $72 Макро команда. Следующий байт – номер саб-команды: Команда – действие 0 Остановить последовательность. 1 Поставить последовательность на паузу. 2 Востановить воспроизведение. Следующий байт не используется, но должен быть задан. 3 Поставить мелодию на паузу. Следующий байт не используется, но должен быть задан. 4 Задать громкость всей мелодии. Имеет байт параметр – величина громкости (0 – самая громкая, $7F – самая тихая). 5 Задать громкость последовательности. Имеет байт параметр – величина громкости (0 – самая громкая, $7F – самая тихая). Величины с $73 до $6F не являются командами и драйвером не используются!
Структура и состав голоса FM GEMS позволяет использовать больше возможностей звукового чипа Yamaha, нежели SMPS, поэтому данных в голосе FM для гемса больше. Рассмотрим их ниже.
| Оффсет | Описание | | $00 | Unknown | | $01 | Unknown | | $02 | Unknown | | $03 | Algorithm (первые 3 бита)/Feedback(следующие 3 бита) | | $04 | Unknown | | $05 | Operator 1 Detune (следующие 3 бита)/Operator 1 Mult (первые 4 бита) | | $06 | Operator 1 TLevel (все 8 бит) | | $07 | Operator 1 KScale (последние 3 бита)/Operator 1 Attack (первые 5 бит) | | $08 | Operator 1 Decay (первые 5 бит)/AM ON/OFF (последний 8 бит) | | $09 | Operator 1 Sustain (первые 5 бит) | | $0A | Operator 1 SLevel (последние 4 бита)/Operator 1 Release (первые 4 бита) | | $0B | Operator 2 Detune (следующие 3 бита)/Operator 2 Mult (первые 4 бита) | | $0C | Operator 2 TLevel (все 8 бит) | | $0D | Operator 2 KScale (следующие 3 бита)/Operator 2 Attack (первые 5 бит) | | $0E | Operator 2 Decay (первые 5 бит)/AM ON/OFF (последний 8 бит) | | $0F | Operator 2 Sustain (первые 5 бит) | | $10 | Operator 2 SLevel (последние 4 бита)/Operator 2 Release (первые 4 бита) | | $11 | Operator 3 Detune (следующие 3 бита)/Operator 3 Mult (первые 4 бита) | | $12 | Operator 3 TLevel (все 8 бит) | | $13 | Operator 3 KScale (последние 3 бита)/Operator 3 Attack (первые 5 бит) | | $14 | Operator 3 Decay (первые 5 бит)/AM ON/OFF (последний 8 бит) | | $15 | Operator 3 Sustain (первые 5 бит) | | $16 | Operator 3 SLevel (последние 4 бита)/Operator 3 Release (первые 4 бита) | | $17 | Operator 4 Detune (следующие 3 бита)/Operator 4 Mult (первые 4 бита) | | $18 | Operator 4 TLevel (все 8 бит) | | $19 | Operator 4 KScale (последние 3 бита)/Operator 4 Attack (первые 5 бит) | | $1A | Operator 4 Decay (первые 5 бит)/AM ON/OFF (последний 8 бит) | | $1B | Operator 4 Sustain (первые 5 бит) | | $1C | Operator 4 SLevel (последние 4 бита)/Operator 4 Release (первые 4 бита) | | $1D-$1E | Operator 1 Ch3 Frequency | | $1F-$20 | Operator 2 Ch3 Frequency | | $21-$22 | Operator 3 Ch3 Frequency | | $23-$24 | Operator 4 Ch3 Frequency |
|