• avatar Shiru
  • 0
Проверяло уже несколько человек. Думаю, записи с железа от кого-нибудь из них скоро появятся.
  • avatar frog
  • 1
> Сразу же после релиза демо проверено на железе, полёт нормальный.
Во, это радует. Было бы классно, если бы человек, который проверял, выложил бы видео на youtube. Увидеть работу на живом железе, пусть и в записи, несопоставимо интереснее, чем на PC. Даже с мерцанием и прочим.
P.S. К слову, как мне кажется, в случае утечки в такой вот ситуации, орги бы пошли навстречу и не посчитали бы это нарушением правил.
  • avatar Shiru
  • 2
Спасибо!

Да, это ценный комментарий. Дело в том, что я проворачиваю этот трюк (написание большого проекта без тестов на железе) не в первый и не в десятый раз, на самых разных платформах, уже очень много лет. У меня есть решения, которые были ранее проверены на железе, и если я не выхожу за их рамки, это даёт 99% уверенности, что всё заработает. А если всё же срабатывает неудачный процент — то это абсолютно точно можно исправить. В данном случае я изначально решил не использовать никаких трюков с перепрограммированием видеоконтроллера (народ недавно умудрился одним безумным трюком выжать больше одной градации яркости). В данной демке всюду просто перекладывание байт из одного места в другое, оно никак не может не заработать. Что могло не заработать: звук, но эту часть я отладил пару лет назад, и она была протестирована на железе (благодаря этому в свежих эмуляторах правильный звук, ранее он всюду эмулировался некорректно, что продемонстрировали мои поделки). Ещё могло не заработать: время доступа к видеопамяти, но это также было проверено моим предыдущим релизом для PET. В общем, это был хорошо осознанный и контролируемый риск, на большом опыте.

Конечно, я всё равно нервничал насчёт того возможного процента, мало ли что, железо древнее, плохо эмулируемое и с труднодоступной документацией. Правила запрещают публиковать работы до пати, и я не мог рисковать случайной утечкой, хотя мне было кого попросить провести тест. Сразу же после релиза демо проверено на железе, полёт нормальный.
  • avatar frog
  • 1
Как по мне, лучшая работа на этом party. Да и вообще очень высокий уровень, не только в плане кода.
Единственное — не очень понимаю, почему выбрана платформа, которая недоступна живьём. Насколько я понял из статьи, ты не проверял, работает ли эта демка на компьютере, для которого написана. Это, вообще говоря, стрёмный момент. Представь, если работа занявшая первое место в oldskool, на самом деле работает только на современном PC (надеюсь, что это не так, конечно).
  • avatar Vinnny
  • 1
2022 CAFePARTY (21-23 October) photos.app.goo.gl/2UgNEB7gC4PPhGDE9
  • avatar Vinnny
  • 2
2022 Demodulation (17-18 September) photos.app.goo.gl/gfXgDxYZbb3u8Njo8
  • avatar nodeus
  • 0
Репа переехала на Гитхаб
  • avatar Vinnny
  • 2
2022 Undefined Summer (20-21 August) photos.app.goo.gl/zH5iQPW6DFZZZVcGA
Отличный выбор человека для интервью, очень интересно узнать о нём хотя бы немного.
Возможно те, кому лень пролистать статью на английском языке даже не заинтересованы этой тематикой?
  • avatar frog
  • 0
Возможно стоит в самом верху написать по-русски, что перевод ниже. Или оформить перевод отдельным постом. Потому что сейчас те, кто не знают английского посчитают, что перевода в посте нет.
Невероятно крутая демо! Спасибо за статью!
  • avatar Vinnny
  • 2
2022 DiHalt Summer Camping (29-31 July) photos.app.goo.gl/HQG8nniH5hv4EbA29
  • avatar sq
  • 0
diver4d , пора писать статью про гамма-чанки, в чём была их идея (и почему мы (я) налажали, и из-за этого никто ничего не понял :)
  • avatar sq
  • 0
Статья не моя, поэтому все плюсы и слава должны достаться MixailV aka Monster^Sage :)
В онлайн-эмуляторе aa-dav.github.io/ доступен новый исходник «bitmap noise» — выбираем пункт и нажимаем «Compile and Run».
После выполнения инициализирующего кода в simple_lib.inc раскладка памяти следующая:
С адреса $8000 располагаются 16384 _слов_ (ячейки памяти 16-битные) описывающие 16-цветный битмап 256x256 (на экране без записи в регистры скроллинга видны верхние 192 строки). Т.к. ячейки — слова, то в каждое слово влезает четыре пикселя по 4 бита цветности на каждый. Раскладка линейная.
Но еще с адреса $C000 располагается зона атрибутов размером 32x32 знакоместа. Атрибут имеет маску PPPP00NN NNNNNNNN, где N это номер выводимого знакоместа в соответствующей квадратной сетке, а PPPP — верхние биты палитры из 256 цветов которые будут добавляться к цветам пикселя. Т.е. номер субпалитры в 16 слотов из 16 субпалитр. Чтобы записать в палитру надо записать в ячейку/порт $FFF6 номер слота палитры (0..255), а в $FFF7 RGB-значение в формате 0RRRRRGGGGGBBBBB.
Таким образом на экране может быть одновременно 256 цветов, но не более чем 16 цветов в знакоместе.
Более того — отображение в знакоместах можно перенастраивать на другие знакоместа через таблицу атрибутов реализуя быстро работающие текстовые видеорежимы ну или игровое тайловое поле с аппаратным скроллингом.
Размышляя на досуге о том не присобачить ли какой-нибудь ЯВУ вместо ассемблера просто подумал — а насколько архитектура Simp4 хорошо ложится на крайне минималистичный язык Forth?
А ведь есть весьма хороший из-за симметричности системы команд уровень «природной» совместимости.
Во первых т.к. в Simp4 нет байтов, а и регистры и ячейки памяти есть 16-битные, то Forth уже удачно ложится по своей безтиповой стековой модели. Угу.
Во вторых если рассмотреть базовые арифметические операции Forth — они производятся над двумя величинами в вершине стека которые замещаются одним результатом.
Но в Simp4 этому крайне удачно соответствует сам принцип работы со стеком и в точности, например, операция форта + будет реализована всего одной машинной командой размером в минимальное одно слово:

[ sp ] = [ sp ] + [ sp ] ; считываем со стека два операнда (с пост-декрементом), суммируем и отправляем обратно в стек (с пост-инкрементом)


Вместо + может быть и минус и вся прочая базовая арифметика процессора.
Такая адресация используя специфичное поведение регистра sp при косвенной адресации реализует именно что базовую модель форта — со стека снимаются два аргумента, помещаются на вход АЛУ (sp каждый раз при «изъятии» пост-декрементируется) и далее результат из АЛУ записывается обратно в стек с пред-инкрементом. Ровно то, что нужно форту.

Сложнее, например, с командой DUP. Она должна продублировать вершину стека. Но записать это как

[ sp ] <- [ sp ]; аналог move с нулём в качестве второго операнда режима сложения с inplace-immediate


нельзя, т.к. sp без альтернатив при косвенном считывании пост-декрементируется, а при записи пост-инкрементируется, это его неизменная фича. А значит мы останемся ни с чем. Просто холостая проброска без изменения состояния машины.
А значит нужно сперва нацелить другой регистр на вершину стека и действие выполняется в две 16-битных инструкции:

r0 <- sp + 0
[ sp ] <- [ r0 ]


Т.е. загоняем в r0 копию указателя на вершину стека и вот её уже дублируем.
Но интересно тут то, что константа 0 в используемом тут режиме inplace-immediate (может полностью отсутствовать с кодом операции + как во второй инструкции) может быть любым числом от -8..+7, что позволяет уложить этот режим в одно слово инструкции. А значит во первых — ряд инструкций которым нужно дотянуться неглубоко в стек (до -8 от вершины) могут использовать этот сокращённый режим инструкции, а форту больше и не надо.

Однако такое удобство стека в Simp4 вроде бы как ставит подножку — использовать его уже понятно, что очень удобно для форта, но как же переходы в другие участки кода (CALL-ы) которые тоже используют стек?
А вот как: в Simp4 на самом деле по архитектуре нет команды CALL, а она эмулируется последовательностью из, например, таких инструкций:

[ sp ] <- pc + 2
pc <- proc_address


Т.е. да, в Simp4 мы всегда сами помещаем в стек «вручную» адрес возврата предварительно его вычислив где опять таки пригождается сложение в режиме inplace-immediate, т.к. желательно уложится в одно слово и потом мы совершаем безусловный прыжок куда надо. Такая последовательность инструкций занимает уже три слова, т.к. proc_address как полное 16-битное слово надо размещать за последней инструкцией. Поэтому в стек в первой команде помещается pc+2 — на момент выполнения этой инструкции pc уже смотрит в начало следующей которая занимает 2 слова, вот мы и вычисляем адрес возврата сразу за ними.
Окей, но это для нас значит, что мы можем вообще изменить стратегию вызова процедур в режиме форта и не использовать для неё регистр sp!
Можно применить совмещённую стратегию программного стека и LINK REGISTER. Договоримся, что регистр r4 указывает на слово сразу под вершиной программного стека для вызова процедур и тогда вызов будем писать так:

[ r4 ] <- pc + 2
pc <- proc_address


Это всё те же три слова инструкций, но регистр r4 сам не декрементируется. У него в отличие от sp такой фичи нет.
Поэтому если процедура не вызывает другие процедуры (leaf-node) она просто не портит r4 и делает возврат тривиально:

pc <- [ r4 ]


И ячейка на которую указывает [ r4 ] снова готова к использованию без какого либо пенальти по сравнению с классическим стилем вызова процедур в Simp4 как я его использую.
Но если процедура собирается вызывать другие процедуры, то она должна начинаться с тривиального пролога:

r4 <- r4 - 1


Просто при входе декрементируем r4 в одну инструкцию-слово.
И возврат из такой процедуры усложняется всего лишь на одно слово:

r4 <- r4 + 1 ; увеличиваем r4 на 1
pc <- [ r4 ] ; переходим по адресу возврата в ячейке куда указывает r4


И вуаля! Такой отказ от использования аппаратного стека для подпрограмм совсем не выглядит катастрофой, обременительные расходы совсем небольшие, а для leaf-node-процедур вообще нулевые. Зато гибкость аппаратного стека для арифметики самого Форта выглядит солидным достижением.

Забавно, забавно. Simp4 оказывается сравнительно дружелюбная архитектура к Форту хотя таковой совсем не планировалась. :)
  • avatar MixailV
  • 0
Спасибо за такой подробный и развернутый ответ!
Кодить что-то своё наврядли буду, просто было интересно )
Про PDM даже мысли в голову не приходили. По идее следующий шаг после PWM — это реализовать дельта-сигма модуляцию!
Забыл ответить точнее на твои варианты. Движков через AND или XOR я не знаю (AND звучит как неважная идея, XOR может и заработать, не пробовал). Идея с чередованием — предпоследняя в моём списке, так делают многие старые движки, да и новые тоже. Недостаток этой идеи: трудно сделать много каналов, т.к. часто делаем out, причём такая схема требует высокой частоты дискретизации (из-за частого переключения порта, мы производим больше высокочастотных помех). Из-за этого, например, движок Wham так сильно свистит.

Squeeker смешивает звуки по OR, что может звучать странно, но работает неплохо. Мой Octode XL как бы складывает каналы вместе и использует сумму как итоговую скважность (фактически, PWM).

Было бы интересно сделать биперный движок на PDM. К сожалению, не знаю как синтезировать PDM с нужной скоростью.
Есть много подходов. Вот прямо из головы несколько:
* Можно выводить звук каждого канала тонкими иголками (тонкими = намного уже периода цикла дискретизации). Тогда громкость можно изобразить меняя ширину иголки. Так были устроены движки Фоллина, и это довольно популярный подход.
* Так как иголки сравнительно узкие, а периоды нот сравнительно длинные, большую часть времени ничего выводить не нужно. Поэтому можно сделать иголки пошире, например шириной в период дискретизации, или даже в несколько. Это идея довольно редкая, но так устроен, например, Octode XL.
* Можно думать об этом как о чём-то вроде ШИМ. Тогда можно просто сделать движок как что-то типа ШИМ движка, и кормить ему сэмплы, как в обычном цифровом движке. utz делал несколько современных движков по такому принципу, и наверное не он один (но я не вспомню сейчас их названия).
* Можно выводить текущее состояние каждого канала звука раз в цикл дискретизации. Типа, 2 канала выдают прямоугольники, каждый со своим периодом, тогда выводим в звуковом цикле поочерёдно состояние каждого из каналов. Так работают Wham the Music Box, Savage, из новых движков Tritone, ну и многие др., это чуть ли не самая «модная» стратегия.
* Можно смешивать подход с иголками и подход с прямоугольниками. Это тоже довольно редкая идея, но Squeeker устроен как раз так. Плюс такой идеи в том, что прямоугольники лучше воспроизводят басы, а иголки дают более разнообразное звучание.
Вроде ничего фундаментального я не забыл, но пишу второпях. Надеюсь, что Shiru дополнит/поправит, если что.