Если здесь есть музыканты, имеющие свой канал на YouTube или паблик ВКонтакте, ответьте мне на один вопрос: знаком ли вам такой способ завоевания популярности, как каверы на музыку из старинных видеоигр? Метод убийственный не только из-за ностальгии.
Смуф МакГрув в одном из интервью упомянул, что был удивлён тем, насколько крутыми были сделаны мелодии для старых игр.
Дело не только в профессионалах, работавших над старыми играми, но и в ограничениях, которые им приходилось преодолевать.
То, что звучит круто, если собрать его из ассемблера, спички и желуди расцветают еще ярче, когда играют на настоящих музыкальных инструментах.
Ну или петь акапелла.
В этой статье я расскажу о том, как в общих чертах работает генерация звука в Ricoh 2A03/2A07, которые использовались на NES. Почему об этом? Ну, не столько я выбираю темы для своих статей, сколько мой пет-проект выбирает их за меня.
Во многом данная статья является пересказом соответствующего раздела nesdev.wiki, который можно найди здесь .
Но это нельзя назвать переводом, так как из других источников было добавлено мало информации.
По сути, это описание того, как генерируется окончательный результат работы пяти ЦАП, взятое из одного из сообщений на форуме вышеупомянутой вики.
Что создавало звук на вашей старой 8-битной системе?
Это было сделано процессором Ricoh 2A03 в регионе NTSC и Ricoh 2A07 в регионе PAL. Различия между ними сводятся к разнице между соответствующими телевизионными стандартами.Здесь я буду говорить о NTSC. Так, процессор NES работает на частоте 1 789 773 герца (1 662 607 в версии PAL).
Да, один миллион семьсот восемьдесят девять тысяч семьсот семьдесят три такта в секунду.
Почему это магическое число важно? Это будет видно позже.
Часть процессора, отвечающая за звук, называется ВСУ .
Его тактовая частота в два раза ниже.
Это также важный факт, который следует помнить.
APU состоит из пяти звуковых генераторов или каналов, каждый из которых управляется четырьмя байтами.
То есть у вас есть четыре байта и вы с помощью локального ассемблера устанавливаете нужные биты, чтобы указать, как приставка должна генерировать белый шум, например.
Другой байт включает/выключает каждый канал.
А еще один управляет счетчиком кадров (подробнее об этом ниже).
Два канала генерируют сигнал прямоугольной формы.
Третий канал издает «треугольный» звук (сигнал в форме своеобразной пилы).
Другой канал производит белый шум.
Последний канал позволяет развернуться и по идее воспроизвести любой звук, но с достаточно жёсткими ограничениями.
Дополнительную жесткость им добавляет то, что процессор из железа 1983 года, помимо звука, должен воспроизводить еще и целую видеоигру.
Общие компоненты
Теперь поговорим о тех вещах, которые используются в нескольких каналах.
Счетчик кадров
Отдельный компонент, который, как ни странно, вообще не имеет никакого отношения к видео.Счетчик кадров также выделяется тем, что он не входит ни в один из пяти наших генераторов звука.
По сути, это часы, генерирующие низкочастотные сигналы.
Имеется счетчик, который увеличивается с каждым циклом APU (два цикла CPU).
Сигналы отправляются на определенный номер.
Ниже находится знак, где Х.
5 означает задержку в один цикл ЦП.
Но сначала о том, какие сигналы подает наш Счетчик кадров.
Существует три типа сигналов.
Четвертькадр, Полукадр и, вдруг, Кадр.
«Четверть» и «Половина» используются другими частями ВСУ.
А сам Frame — это прерывание процессора, о работе которого в NES стоит рассказать в другой статье.
Прерывание процессора можно отключить, если оно вам не нужно.
Н.
Б.
Короче говоря, прерывание процессора — это событие, которое заставляет процессор выполнять код, который его обрабатывает. Те, у кого в университете были лабораторные работы по ассемблеру, помнят, как нажатие клавиши на клавиатуре несмотря ни на что тянуло вашу программу к определенному фрагменту кода.
Пройдены циклы APU | Что происходит |
---|---|
3728.5 | Отправляется сигнал четверти кадра.
|
7456.5 | Передаются сигналы половины и четверти кадра.
|
11185.5 | Отправляется сигнал четверти кадра.
|
14914 | Установлен флаг, вызывающий прерывание процессора.
|
14914.5 | Устанавливается флаг, который запускает прерывание процессора и отправляются сигналы половины и четверти кадра.
|
0 (14915) | Устанавливается флаг, вызывающий прерывание процессора, счетчик циклов обнуляется |
Это соответствует 59,99909 прерываниям процессора в секунду.
Почти 60 кадров в секунду.
Ну и соответственно почти 240 «четвертей» и 120 «половинок» в секунду.
Также стоит упомянуть «медленный» режим, для переключения на который есть отдельный флажок.
Вот знак:
Пройдены циклы APU | Что происходит |
---|---|
3728.5 | Отправляется сигнал четверти кадра.
|
7456.5 | Передаются сигналы половины и четверти кадра |
11185.5 | Отправляется сигнал четверти кадра.
|
14914.5 | Ничего |
18640.5 | Передаются сигналы половины и четверти кадра |
0 (18641) | Счетчик сброшен |
В медленном режиме прерывание процессора отсутствует. 48,00635 циклов в секунду дает нам примерно 96 полукадров в секунду и около 192 четвертей кадров в секунду.
Еще отмечу, что счетчик кадров на весь APU всего один, в отличие от тех компонентов, которые я буду рассматривать дальше.
Счетчик длины
Счетчики длины каждый для своего канала.Он есть в четырех каналах из пяти: генераторах прямоугольных, треугольных и шумовых волн.
Состояние этого счетчика описывается флагом «вкл/выкл» (туда можно записать значение) и, собственно, счетчиком.
Когда мы пишем «выключено», этот счетчик принудительно обнуляется и значение, которое там было, теряется.
Непосредственно со счетчиком тоже все не так просто.
Мы не можем перечислить это напрямую.
Вместо этого у нас есть ЛУТ на 32 позиции и пять бит для выбора одного из предустановленных значений.
Если я приведу эти значения подряд, они покажутся вам бессмысленными, поэтому сразу скопируйте-вставьте значения этой таблицы из вики nesdev, соответствующие тому, как эта штука физически размещена на чипе (и хотя бы немного логики).
Legend:
<bit pattern> (<value of bit pattern>) => <note length>
Linear length values:
1 1111 (1F) => 30
1 1101 (1D) => 28
1 1011 (1B) => 26
1 1001 (19) => 24
1 0111 (17) => 22
1 0101 (15) => 20
1 0011 (13) => 18
1 0001 (11) => 16
0 1111 (0F) => 14
0 1101 (0D) => 12
0 1011 (0B) => 10
0 1001 (09) => 8
0 0111 (07) => 6
0 0101 (05) => 4
0 0011 (03) => 2
0 0001 (01) => 254
Notes with base length 12 (4/4 at 75 bpm):
1 1110 (1E) => 32 (96 times 1/3, quarter note triplet)
1 1100 (1C) => 16 (48 times 1/3, eighth note triplet)
1 1010 (1A) => 72 (48 times 1 1/2, dotted quarter)
1 1000 (18) => 192 (Whole note)
1 0110 (16) => 96 (Half note)
1 0100 (14) => 48 (Quarter note)
1 0010 (12) => 24 (Eighth note)
1 0000 (10) => 12 (Sixteenth)
Notes with base length 10 (4/4 at 90 bpm, with relative durations being the same as above):
0 1110 (0E) => 26 (Approx. 80 times 1/3, quarter note triplet)
0 1100 (0C) => 14 (Approx. 40 times 1/3, eighth note triplet)
0 1010 (0A) => 60 (40 times 1 1/2, dotted quarter)
0 1000 (08) => 160 (Whole note)
0 0110 (06) => 80 (Half note)
0 0100 (04) => 40 (Quarter note)
0 0010 (02) => 20 (Eighth note)
0 0000 (00) => 10 (Sixteenth)
Теперь о поведении этого счетчика.
Я уже упоминал, что если его отключить, то сам счетчик обнуляется и игнорируется.
Если он включен, то он уменьшается на вышеупомянутый счетчик кадров.
Каждый сигнал «Полукадра» уменьшает счетчик на единицу, если там есть что уменьшать.
То есть это -120/96 значения счетчика в секунду.
Вся нота для нас длится, выходит,
секунды.
Если счетчик равен нулю и включен, то звук на канале естественно приглушен.
Конверт (конверт, точнее пародия на него)
Эта штука управляет громкостью и ее уменьшением по трем из пяти каналов: квадратичному и шумовому.Треугольный канал имеет свою атмосферу.
Канал дельта-модуляции имеет свою собственную атмосферу.
Громкость на всех трех каналах задается четырьмя битами, что дает нам выходные значения от 0 до 15. И у нас есть так называемый «Параметр огибающей» из четырех бит, который позволяет нам устанавливать громкость.
Но это не так просто.
Для начала дадим общую схему механизма, который дает нам эти значения.
Общая схема снова была украдена из вики nesdev.
Видите четвертькадровые часы? Да, это наш старый друг, счетчик кадров.
И с частотой 240/192 герц (примерно) он нам меняет огибающую.
Начнем со стартового флага.
Он дает нам добро на начало обратного отсчета.
Он устанавливается, если кто-то меняет длину (см.
раздел «Счетчик длины» выше) или частоту ноты.
Это сделано потому, что длина и частота ноты расположены рядом и менять их можно только вместе, но об этом позже.
Если флаг запуска установлен, то мы сбрасываем его, загружаем 15 в Decay Level и загружаем текущий параметр Envelope в Divider. Это наш стартовый состав.
Если флаг запуска уже сброшен, мы уменьшаем Делитель на единицу.
Если наш Делитель был равен нулю, то вместо -1 мы снова устанавливаем Параметр Конверта.
В этот же момент мы уменьшаем Уровень распада на единицу.
Decay Level и дает нам постоянно уменьшающуюся громкость от 15 до 0. Получается что-то вроде двух вложенных циклов for.
раз, где V — параметр огибающей.
V + 1, потому что один из циклов циклически перебирает все значения от 0 до V. Результирующая длительность ноты тогда будет равна
секунд, если не включен медленный режим счетчика кадров.
Когда уровень затухания достигает 0, в игру вступает флаг цикла.
Если он установлен, заряжаем там снова 15, и нота снова начинает играть с переменной громкостью.
То есть уменьшение громкости от максимума до нуля повторяется.
Когда флаг цикла снят, наш нисходящий объем остается на нуле.
Давайте рассмотрим еще один важный флаг, влияющий на конечный результат. Постоянный флаг.
Он отвечает за переключение между «мы устанавливаем громкость непосредственно через параметр огибающей» и «полагаемся на обратный отсчет».
Если этот флаг установлен, уровень затухания игнорируется, но продолжает рассматриваться по тем же правилам .
Это означает, что если вы захотите переключаться между этими режимами в рамках одной заметки, вас ждет много интересного и увлекательного.
Судя по всему, схема для этого не предназначена, но что-то мне подсказывает, что могут быть сумасшедшие, которые выставят громкость на полную, а потом сбрасывают флаг Constant в середине ноты, мирясь с тем, что обратный отсчет громкости на самом деле начинался не с 15, а с, например, 10, до которого успел опуститься Уровень распада.
Флаг остановки/цикла
Да, флаг остановки из счетчика длины и флаг цикла из конверта — это один и тот же бит. То есть у вас есть выбор между конечной нотой и бесконечной нотой.Если вы выбрали конечную ноту, она будет отключена тем, кому удастся первым довести обратный отсчет до нуля.
Вам придется сделать некоторые расчеты, чтобы предсказать, на какой громкости нота сломается.
А если ваша нота бесконечна, то либо устанавливайте громкость сами, либо занимайтесь громкостью, идущей по кругу от 15 до 1. Да, никто не говорил, что будет легко.
Положение дел
Закончим отдельным однобайтовым регистром.Он содержит пять бит записи/чтения, которые включают/выключают наши пять звуковых генераторов.
Все каналы, кроме канала дельта-модуляции, отключаются немедленно после очистки счетчика длины.
В канале дельта-модуляции количество оставшихся байтов установлено равным нулю.
Чтение работает симметрично в том смысле, что мы получим единицу, если соответствующий счетчик длины (или счетчик оставшихся байт выборки) больше нуля.
Еще два бита устанавливаются прерываниями от счетчика кадров и канала дельта-модуляции (к этому мы вернемся позже).
каналы
Теперь, когда мы рассмотрели общие компоненты, давайте рассмотрим каждый звуковой генератор по отдельности.
Прямоугольный
Сказать, что эта часть чипа генерирует звук, было бы не совсем верно.
Он генерирует число от 0 до 15, которое затем используется для создания звуковой волны определенной громкости.
Громкость — это амплитуда, так устроен звук.
Амплитуда — это высота тех самых столбцов, которые вы видите на картинке выше.
И это самое число от 0 до 15 определяется с помощью Конверта, который я описал выше.
Теперь посмотрим на ту часть, которая отсекает из этого потока четные столбцы прямоугольного сигнала в диапазоне «0-15».
Для определения формы сигнала предусмотрены четыре LUT, из которых можно выбрать нужный, используя два бита в регистрах, управляющих прямоугольным сигналом.
Эти таблицы выглядят следующим образом:
Значение обязанности | Соответствующий ЛУТ | Как выглядит выходной сигнал? |
---|---|---|
0 | 0 0 0 0 0 0 0 1 | 0 1 0 0 0 0 0 0 (12.5%) |
1 | 0 0 0 0 0 0 1 1 | 0 1 1 0 0 0 0 0 (25%) |
2 | 0 0 0 0 1 1 1 1 | 0 1 1 1 1 0 0 0 (50%) |
3 | 1 1 1 1 1 1 0 0 | 1 0 0 1 1 1 1 1 (25% отрицательные) |
Третий касается деталей реализации.
Как вы уже догадались, форма выходного сигнала задается циклом от 0 до 7. Точнее, от 0 до 1. На старте переменная, отвечающая за текущее значение из LUT, инициализируется значением 0, но оно меняется в сторону уменьшения.
То есть: 0, 7, 6, 5, 4, 3, 2, 1. Теперь рассмотрим вопрос частоты волн.
Частота звука будет зависеть от того, насколько быстро выполняется этот цикл.
И эта скорость настроена так, чтобы было удобно инженерам Nintendo, а не вам.
Выше я уже упоминал, что частота и длина ноты указываются вместе.
И задаются они двумя байтами, где на длину ноты отведено 5 бит, а на частоту — 11. У нас есть число от 0 до 2047. Пусть это будет t. Каждый такт APU переменная, отвечающая за такт секвенсора, уменьшается на единицу.
Если есть ноль, он становится t. При этом текущая фаза звуковой волны меняется в сторону уменьшения (0, 7, 6, 5, 4, 3, 2, 1).
Весь цикл колебаний нашей прямоугольной волны занимает
Циклы процессора.
Таким образом, если нам нужна частота f, нам нужно вычислить t по следующей формуле:
Не забудьте округлить и помните, что если вы установите t меньше 8, ваш прямоугольный звук превратится в тыквенный.
Не то чтобы она чем-то отличалась от тыквы.
Чем меньше t, тем выше частота, потолок около 12,4 килогерца.
Pulse Sweep, или единственная разница между двумя генераторами квадратичного звука NES.
Чтобы облегчить жизнь композиторам на NES, на управление механизмом развертки, позволяющим менять частоту на лету, щедро выделен целый байт. Он позволяет изменять значение t. У нас есть:- Флаг включения/выключения (1 бит)
- Значение периода изменения частоты P (3 бита)
- Флаг отрицания, выбирает между уменьшением/увеличением t (1 бит)
- S, который определяет, насколько изменить (3 бита)
Соответственно, когда мы переключаемся с 0 на P, один раз в каждом полукадре сигналов P+1 происходит волшебство.
t изменяется не на фиксированное число, а на процент, указанный с помощью S. Это достигается следующим образом:
- Берется копия текущего t и сдвигается на S бит вправо.
- Если флажок «Отрицать» установлен, значение первого элемента становится отрицательным.
- t = t + c из пункта 2
И вот разница между ними: пункт 2, «сделать с отрицательным».
В первом канале это делается с помощью обратный код (получается -s-1), а во втором использовании дополнительный (оказывается -с).
Судя по всему, монета, с помощью которой разработчики чипа решили этот вопрос, упала ребром.
Кстати, помните, я говорил, что нельзя ставить t меньше 8? Это было сделано для защиты от этого механизма.
Цикл, привязанный к P, продолжит слегка вращаться, но сам t не изменится.
Именно поэтому, кстати, некоторые разработчики предпочитали вообще не использовать высшую доступную октаву.
От греха подальше.
Треугольный
Опять смешные картинки.
Обратите внимание, что у нас здесь нет конверта.
Почему? Потому что объем треугольного канала одинаковый.
А она одна, потому что делать вариации было слишком сложно и не стоило (это же начало 80-х, чего вы хотели).
Выходные данные — это текущее значение из следующей LUT:
15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
На этот раз с каждым циклом мы отправляем на выход новое значение из приведенного выше LUT. Но есть нюанс — этот таймер тикает каждый цикл Процессор .
А частота рассчитывается по другой формуле:
Механизма Sweep нет, и поэтому канал в t < 8 is not muted. Here we have a range of frequencies up to 55 kilohertz, that is, beyond the bar where ultrasound already begins. It is all the more ironic that the triangular sound is used as a “basukha”.
Triangular waves sound very juicy in low frequencies. Линейный счетчик — это усеченная версия счетчика длины, которая управляется одним байтом.
Бит предназначен для включения/выключения, а остальные семь — значение счетчика.
Счетчик уменьшается на единицу с каждой четвертькадровым сигналом.
Семь бит — 127 сигналов четверти кадра.
Это чуть больше полсекунды, поэтому такая возможность использовалась довольно редко.
Шумовой
А теперь давайте откопаем наши университетские конспекты по криптографии и вспомним, что ЛФСР , также известный как регистр сдвига с линейной обратной связью.
Зачем нам это нужно? Скажем так, структура этого канала аналогична квадратичной, с той разницей, что 0/1 в локальном секвенсоре определяется не LUT с четными полосками, а генератором случайных чисел.
Какой еще может быть генератор случайных чисел, аппаратно реализованный в простом чипе? Позвольте мне напомнить/рассказать вам, что это такое.
Есть регистр, который содержит определенное количество бит. В нашем случае - 15, и нумеруются они так: 14 - 13 - 12 - 11 - 10 - 9 - 8 - 7 - 6 - 5 - 4 - 3 - 2 - 1 - 0. На каждом шаге происходит следующее:
- Новый бит мы вычисляем по формуле, которую легко реализовать аппаратно.
Это один бит, 0/1.
- Мы сдвигаем наш регистр на один бит вправо.
- Вновь вычисленный 14-й бит помещается в свободное пространство.
- Речь уже не о LFSR, но хотелось бы обратить ваше внимание на то, что бит 0 идёт в секвенсор.
У нас есть две формулы, и за выбор между ними отвечает специальный флаг Mode:
- Если флаг режима сброшен, результатом является XOR между 0 и 1 битами.
В результате получается последовательность из 32 767 чисел, которая звучит как «пш-ш-ш-ш-ш-ш» (белый шум телевизора).
- Если флаг Mode установлен, результатом будет XOR 0 и 6 бит. В результате получается последовательность из 93 или 31 числа (в зависимости от того, когда вы установите флажок), которая звучит как «пи-и-и-и-и-и-и-и» (вы знаете этот звук по телевизору, когда трансляция уже закончилась и остается только таблица настройки).
А вот с переключением на следующий бит, то есть с регулированием частоты, все по-другому.
Локальный T берется из четырехбитного LUT, который выглядит (в версии NTSC) так:
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | А | Б | С | Д | ? | Ф |
4 | 8 | 16 | 32 | 64 | 96 | 128 | 160 | 202 | 254 | 380 | 508 | 762 | 1016 | 2034 | 4068 |
11 бит, которые регулируют частоту в других каналах, здесь не действуют. Обычно этот канал имеет два применения.
Во-первых, взрывы и прочие «пых-пых-пых».
Если вы установите параметр локальной частоты на 10 и сыграете это короткими нотами, вы сможете услышать взрыв моста в джунглях из Contra. Во-вторых, перкуссия и прочие шумовые непристойности, вносящие разнообразие в музыку.
Дельта-модуляция
Ой.
Здесь, что называется, «своя атмосфера».
Например, здесь вообще нет двухбайтовой структуры длины ноты и таймера частоты.
Двух типов писков и белого шума недостаточно для создания музыки, с какой стороны на это ни посмотри.
Поэтому вы можете перетаскивать короткие звуки из памяти и воспроизводить их через этот канал.
Конечно, без горы технических ограничений этого сделать невозможно.
Что такое дельта-модуляция? Это когда вы записываете не текущую фазу звуковой волны напрямую, как это делается в PCM (.
wav без всякого сжатия, например), а разницу между ними.
В случае, например, с белым шумом толку ноль.
Но если мы заменим последовательность чисел «0, 1, 2, 3, 4, 5, 6, 8, 10, 11, 10.» на «1, 1, 1, 1, 1, 1, 2, 2, 1, -1", то его будет легче сжимать и хранить (маленькие числа требуют меньше битов).
Здесь эта идея развернута до максимума.
Этот звуковой генератор выдает на выходе диапазон 0-127, а не 0-15, как у остальных.
Мелодия здесь однобитная, где 0 в битовом потоке означает
, и 1 -
.
Если результат меньше 0 или больше 127, то следующий бит игнорируется.
Конечно, это вас сильно ограничивает, но другого способа разнообразить музыку или произвести особый звук по случаю прыжка, например, у нас нет. Теперь посмотрим, как управляется это счастье (все только на запись):
- Адрес.
- Длина.
Длина образца
. - Ставка.
Время до переключения на следующий бит указывается в циклах Процессор .
- Петля.
- прерывание.
- Прямая нагрузка.
Семь бит предназначены для непосредственной настройки выхода, минуя механизм загрузки дельта-выборки.
Постоянно меняя этот 0-127, теоретически можно воспроизводить любую музыку.
На практике игру тоже нужно показывать, поэтому это счастье используется только в заставках.
Уточним, это циклы ЦП, то есть частота делится непосредственно на это число.
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | А | Б | С | Д | ? | Ф |
428 | 380 | 340 | 320 | 286 | 254 | 226 | 214 | 190 | 160 | 142 | 128 | 106 | 84 | 72 | 54 |
И как из всего этого создается музыка?
У нас есть пять звуковых генераторов.Четыре из них дают числа от 0 до 15. Один из них от 0 до 127. Остаётся самое главное: издавать из этого звуки.
Вывод: Миксер
Если вы думаете, что существует одна фишка, объединяющая пять чисел, то черт возьми.Дальше начинается чистая физика, которая самыми олдскульными методами превращает пять чисел в звуки.
Для динамика единственным выходом, номером, из которого создается звуковая волна, является напряжение, напряжение.
Здесь я расскажу о том, как рассчитывается это напряжение.
Так как физика не моя сильная сторона, буду рад любым уточнениям и исправлениям в комментариях.
Каждый звуковой генератор имеет свой собственный ЦАП .
Щас будет рассказ о той части, которая мне не нравилась в школе, поэтому ссылка на источник .
Каждый ЦАП ведет себя как резистор по принципу «чем больше выход, тем меньше сопротивление»:
.
Ниже р базовый все каналы.
Канал | Сопротивление, Ом |
---|---|
квадратичный | 8128 |
Треугольный | 8227 |
Шумовой | 12241 |
Дельта модуляция.
|
22638 |
Остальные три подключаются параллельно в другую группу.
Выходное напряжение обеих групп формируется делителем напряжения с резистором сопротивлением 100 Ом.
На вход этого делителя изнутри микросхемы подается ток напряжением 1,17 вольт. Наконец все это смешивается с помощью двух резисторов номиналом 12 и 20 кОм.
Получается, что пропорция 3/5, где квадратичным звукам отдается 3 части, а всем остальным - 5. Это напряжение подается на динамики.
Из всего этого была составлена следующая формула для использования в эмуляторах:
В результате получается диапазон от 0,0 до 1,0, который можно использовать для генерации звука в любом удобном для вас формате.
Самое смешное, что это еще не конец, и вывод пропускается через несколько фильтров.
Но это я оставлю тем, кто понимает, что изображено на картинке ниже.
Вход: 22 магических байта.
Теперь мы точно знаем, как пять звуковых генераторов создают звук.
Но как их контролировать? Как заставить их играть музыку? Здесь вы можете включить магию программирования на локальном ассемблере.
Каждый из пяти звуковых генераторов имеет четыре регистра только для записи по одному байту каждый.
Все эти биты, флаги, байты, о которых я говорил выше, распределены по четыре байта для каждого звукового генератора.
Еще два байтовых регистра живут отдельно.
Один управляет счетчиком кадров, а второй используется для определения/изменения состояния включения/выключения всех каналов.
Регистры | часть ВСУ | Примечания |
---|---|---|
$4000-$4003 | Первый квадратичный канал | |
$4004-$4007 | Второй квадратичный канал | |
4008-400 миллиардов долларов | Треугольный канал | |
$400-$400F | Шумовой канал | |
$4010-$4013 | Дельта-канал модуляции | |
$4015 | Управляйте другими каналами, см.
раздел «Статус» выше.
|
Единственный регистр, который может быть читать .
|
$4017 | Счетчик кадров |
reset:
lda #$01 ; square 1
sta $4015
lda #$08 ; period low
sta $4002
lda
Теги: #nes #Старое оборудование #звук и музыка